Files
ComfyUI_frontend/tests-ui/tests/litegraph/subgraph/Subgraph.test.ts
snomiao 8bfb1009ce [style] migrate to @prettier/plugin-oxc for faster formatting
Replace @trivago/prettier-plugin-sort-imports with @prettier/plugin-oxc
and @ianvs/prettier-plugin-sort-imports for improved performance.

Changes:
- Add @prettier/plugin-oxc (Rust-based fast parser)
- Add @ianvs/prettier-plugin-sort-imports (import sorting compatible with oxc)
- Remove @trivago/prettier-plugin-sort-imports
- Update .prettierrc to use new plugins and compatible import order config
- Reformat all files with new plugin configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 00:02:04 +00:00

331 lines
11 KiB
TypeScript

// TODO: Fix these tests after migration
/**
* Core Subgraph Tests
*
* This file implements fundamental tests for the Subgraph class that establish
* patterns for the rest of the testing team. These tests cover construction,
* basic I/O management, and known issues.
*/
import { describe, expect, it } from 'vitest'
import {
createUuidv4,
LGraph,
RecursionError,
Subgraph
} from '@/lib/litegraph/src/litegraph'
import { subgraphTest } from './fixtures/subgraphFixtures'
import {
assertSubgraphStructure,
createTestSubgraph,
createTestSubgraphData
} from './fixtures/subgraphHelpers'
describe.skip('Subgraph Construction', () => {
it('should create a subgraph with minimal data', () => {
const subgraph = createTestSubgraph()
assertSubgraphStructure(subgraph, {
inputCount: 0,
outputCount: 0,
nodeCount: 0,
name: 'Test Subgraph'
})
expect(subgraph.id).toMatch(
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
)
expect(subgraph.inputNode).toBeDefined()
expect(subgraph.outputNode).toBeDefined()
expect(subgraph.inputNode.id).toBe(-10)
expect(subgraph.outputNode.id).toBe(-20)
})
it('should require a root graph', () => {
const subgraphData = createTestSubgraphData()
expect(() => {
// @ts-expect-error Testing invalid null parameter
new Subgraph(null, subgraphData)
}).toThrow('Root graph is required')
})
it('should accept custom name and ID', () => {
const customId = createUuidv4()
const customName = 'My Custom Subgraph'
const subgraph = createTestSubgraph({
id: customId,
name: customName
})
expect(subgraph.id).toBe(customId)
expect(subgraph.name).toBe(customName)
})
it('should initialize with empty inputs and outputs', () => {
const subgraph = createTestSubgraph()
expect(subgraph.inputs).toHaveLength(0)
expect(subgraph.outputs).toHaveLength(0)
expect(subgraph.widgets).toHaveLength(0)
})
it('should have properly configured input and output nodes', () => {
const subgraph = createTestSubgraph()
// Input node should be positioned on the left
expect(subgraph.inputNode.pos[0]).toBeLessThan(100)
// Output node should be positioned on the right
expect(subgraph.outputNode.pos[0]).toBeGreaterThan(300)
// Both should reference the subgraph
expect(subgraph.inputNode.subgraph).toBe(subgraph)
expect(subgraph.outputNode.subgraph).toBe(subgraph)
})
})
describe.skip('Subgraph Input/Output Management', () => {
subgraphTest('should add a single input', ({ emptySubgraph }) => {
const input = emptySubgraph.addInput('test_input', 'number')
expect(emptySubgraph.inputs).toHaveLength(1)
expect(input.name).toBe('test_input')
expect(input.type).toBe('number')
expect(emptySubgraph.inputs.indexOf(input)).toBe(0)
})
subgraphTest('should add a single output', ({ emptySubgraph }) => {
const output = emptySubgraph.addOutput('test_output', 'string')
expect(emptySubgraph.outputs).toHaveLength(1)
expect(output.name).toBe('test_output')
expect(output.type).toBe('string')
expect(emptySubgraph.outputs.indexOf(output)).toBe(0)
})
subgraphTest(
'should maintain correct indices when adding multiple inputs',
({ emptySubgraph }) => {
const input1 = emptySubgraph.addInput('input_1', 'number')
const input2 = emptySubgraph.addInput('input_2', 'string')
const input3 = emptySubgraph.addInput('input_3', 'boolean')
expect(emptySubgraph.inputs.indexOf(input1)).toBe(0)
expect(emptySubgraph.inputs.indexOf(input2)).toBe(1)
expect(emptySubgraph.inputs.indexOf(input3)).toBe(2)
expect(emptySubgraph.inputs).toHaveLength(3)
}
)
subgraphTest(
'should maintain correct indices when adding multiple outputs',
({ emptySubgraph }) => {
const output1 = emptySubgraph.addOutput('output_1', 'number')
const output2 = emptySubgraph.addOutput('output_2', 'string')
const output3 = emptySubgraph.addOutput('output_3', 'boolean')
expect(emptySubgraph.outputs.indexOf(output1)).toBe(0)
expect(emptySubgraph.outputs.indexOf(output2)).toBe(1)
expect(emptySubgraph.outputs.indexOf(output3)).toBe(2)
expect(emptySubgraph.outputs).toHaveLength(3)
}
)
subgraphTest('should remove inputs correctly', ({ simpleSubgraph }) => {
// Add a second input first
simpleSubgraph.addInput('second_input', 'string')
expect(simpleSubgraph.inputs).toHaveLength(2)
// Remove the first input
const firstInput = simpleSubgraph.inputs[0]
simpleSubgraph.removeInput(firstInput)
expect(simpleSubgraph.inputs).toHaveLength(1)
expect(simpleSubgraph.inputs[0].name).toBe('second_input')
// Verify it's at index 0 in the array
expect(simpleSubgraph.inputs.indexOf(simpleSubgraph.inputs[0])).toBe(0)
})
subgraphTest('should remove outputs correctly', ({ simpleSubgraph }) => {
// Add a second output first
simpleSubgraph.addOutput('second_output', 'string')
expect(simpleSubgraph.outputs).toHaveLength(2)
// Remove the first output
const firstOutput = simpleSubgraph.outputs[0]
simpleSubgraph.removeOutput(firstOutput)
expect(simpleSubgraph.outputs).toHaveLength(1)
expect(simpleSubgraph.outputs[0].name).toBe('second_output')
// Verify it's at index 0 in the array
expect(simpleSubgraph.outputs.indexOf(simpleSubgraph.outputs[0])).toBe(0)
})
})
describe.skip('Subgraph Serialization', () => {
subgraphTest('should serialize empty subgraph', ({ emptySubgraph }) => {
const serialized = emptySubgraph.asSerialisable()
expect(serialized.version).toBe(1)
expect(serialized.id).toBeTruthy()
expect(serialized.name).toBe('Empty Test Subgraph')
expect(serialized.inputs).toHaveLength(0)
expect(serialized.outputs).toHaveLength(0)
expect(serialized.nodes).toHaveLength(0)
expect(typeof serialized.links).toBe('object')
})
subgraphTest(
'should serialize subgraph with inputs and outputs',
({ simpleSubgraph }) => {
const serialized = simpleSubgraph.asSerialisable()
expect(serialized.inputs).toHaveLength(1)
expect(serialized.outputs).toHaveLength(1)
// @ts-expect-error TODO: Fix after merge - serialized.inputs possibly undefined
expect(serialized.inputs[0].name).toBe('input')
// @ts-expect-error TODO: Fix after merge - serialized.inputs possibly undefined
expect(serialized.inputs[0].type).toBe('number')
// @ts-expect-error TODO: Fix after merge - serialized.outputs possibly undefined
expect(serialized.outputs[0].name).toBe('output')
// @ts-expect-error TODO: Fix after merge - serialized.outputs possibly undefined
expect(serialized.outputs[0].type).toBe('number')
}
)
subgraphTest(
'should include input and output nodes in serialization',
({ emptySubgraph }) => {
const serialized = emptySubgraph.asSerialisable()
expect(serialized.inputNode).toBeDefined()
expect(serialized.outputNode).toBeDefined()
expect(serialized.inputNode.id).toBe(-10)
expect(serialized.outputNode.id).toBe(-20)
}
)
})
describe.skip('Subgraph Known Issues', () => {
it.todo('should enforce MAX_NESTED_SUBGRAPHS limit', () => {
// This test documents that MAX_NESTED_SUBGRAPHS = 1000 is defined
// but not actually enforced anywhere in the code.
//
// Expected behavior: Should throw error when nesting exceeds limit
// Actual behavior: No validation is performed
//
// This safety limit should be implemented to prevent runaway recursion.
})
it('should provide MAX_NESTED_SUBGRAPHS constant', () => {
expect(Subgraph.MAX_NESTED_SUBGRAPHS).toBe(1000)
})
it('should have recursion detection in place', () => {
// Verify that RecursionError is available and can be thrown
expect(() => {
throw new RecursionError('test recursion')
}).toThrow(RecursionError)
expect(() => {
throw new RecursionError('test recursion')
}).toThrow('test recursion')
})
})
describe.skip('Subgraph Root Graph Relationship', () => {
it('should maintain reference to root graph', () => {
const rootGraph = new LGraph()
const subgraphData = createTestSubgraphData()
const subgraph = new Subgraph(rootGraph, subgraphData)
expect(subgraph.rootGraph).toBe(rootGraph)
})
it('should inherit root graph in nested subgraphs', () => {
const rootGraph = new LGraph()
const parentData = createTestSubgraphData({
name: 'Parent Subgraph'
})
const parentSubgraph = new Subgraph(rootGraph, parentData)
// Create a nested subgraph
const nestedData = createTestSubgraphData({
name: 'Nested Subgraph'
})
const nestedSubgraph = new Subgraph(rootGraph, nestedData)
expect(nestedSubgraph.rootGraph).toBe(rootGraph)
expect(parentSubgraph.rootGraph).toBe(rootGraph)
})
})
describe.skip('Subgraph Error Handling', () => {
subgraphTest(
'should handle removing non-existent input gracefully',
({ emptySubgraph }) => {
// Create a fake input that doesn't belong to this subgraph
const fakeInput = emptySubgraph.addInput('temp', 'number')
emptySubgraph.removeInput(fakeInput) // Remove it first
// Now try to remove it again
expect(() => {
emptySubgraph.removeInput(fakeInput)
}).toThrow('Input not found')
}
)
subgraphTest(
'should handle removing non-existent output gracefully',
({ emptySubgraph }) => {
// Create a fake output that doesn't belong to this subgraph
const fakeOutput = emptySubgraph.addOutput('temp', 'number')
emptySubgraph.removeOutput(fakeOutput) // Remove it first
// Now try to remove it again
expect(() => {
emptySubgraph.removeOutput(fakeOutput)
}).toThrow('Output not found')
}
)
})
describe.skip('Subgraph Integration', () => {
it("should work with LGraph's node management", () => {
const subgraph = createTestSubgraph({
nodeCount: 3
})
// Verify nodes were added to the subgraph
expect(subgraph.nodes).toHaveLength(3)
// Verify we can access nodes by ID
const firstNode = subgraph.getNodeById(1)
expect(firstNode).toBeDefined()
expect(firstNode?.title).toContain('Test Node')
})
it('should maintain link integrity', () => {
const subgraph = createTestSubgraph({
nodeCount: 2
})
const node1 = subgraph.nodes[0]
const node2 = subgraph.nodes[1]
// Connect the nodes
node1.connect(0, node2, 0)
// Verify link was created
expect(subgraph.links.size).toBe(1)
// Verify link integrity
const link = Array.from(subgraph.links.values())[0]
expect(link.origin_id).toBe(node1.id)
expect(link.target_id).toBe(node2.id)
})
})