mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 19:09:52 +00:00
This PR cleans up the base-layer utilities so they no longer pull renderer or workbench code. The renderer-only `isPrimitiveNode` guard now lives in `src/renderer/utils/nodeTypeGuards.ts`, and the node help/model/ordering helpers have moved into `src/workbench/utils`. All affected services, stores, scripts, and tests were updated to import from the new locations. The idea is to reduce the number of Base→Renderer/Base→Workbench edges (higher scoped base/common utils should not import from renderer/workbench layers). ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6621-refactor-move-renderer-dependent-utils-into-workbench-scope-2a36d73d36508167aff0fc8a22202d7f) by [Unito](https://www.unito.io)
163 lines
5.4 KiB
TypeScript
163 lines
5.4 KiB
TypeScript
import { beforeEach, describe, expect, it } from 'vitest'
|
|
|
|
import { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
|
import type { ISerialisedNode } from '@/lib/litegraph/src/types/serialisation'
|
|
import { sortWidgetValuesByInputOrder } from '@/workbench/utils/nodeDefOrderingUtil'
|
|
|
|
describe('LGraphNode widget ordering', () => {
|
|
let node: LGraphNode
|
|
|
|
beforeEach(() => {
|
|
node = new LGraphNode('TestNode')
|
|
})
|
|
|
|
describe('configure with widgets_values', () => {
|
|
it('should apply widget values in correct order when widgets order matches input_order', () => {
|
|
// Create node with widgets
|
|
node.addWidget('number', 'steps', 20, null, {})
|
|
node.addWidget('number', 'seed', 0, null, {})
|
|
node.addWidget('text', 'prompt', '', null, {})
|
|
|
|
// Configure with widget values
|
|
const info: ISerialisedNode = {
|
|
id: 1,
|
|
type: 'TestNode',
|
|
pos: [0, 0],
|
|
size: [200, 100],
|
|
flags: {},
|
|
order: 0,
|
|
mode: 0,
|
|
widgets_values: [30, 12345, 'test prompt']
|
|
}
|
|
|
|
node.configure(info)
|
|
|
|
// Check widget values are applied correctly
|
|
expect(node.widgets![0].value).toBe(30) // steps
|
|
expect(node.widgets![1].value).toBe(12345) // seed
|
|
expect(node.widgets![2].value).toBe('test prompt') // prompt
|
|
})
|
|
|
|
it('should handle mismatched widget order with input_order', () => {
|
|
// Simulate widgets created in wrong order (e.g., from unordered Object.entries)
|
|
// but widgets_values is in the correct order according to input_order
|
|
node.addWidget('number', 'seed', 0, null, {})
|
|
node.addWidget('text', 'prompt', '', null, {})
|
|
node.addWidget('number', 'steps', 20, null, {})
|
|
|
|
// Widget values are in input_order: [steps, seed, prompt]
|
|
const info: ISerialisedNode = {
|
|
id: 1,
|
|
type: 'TestNode',
|
|
pos: [0, 0],
|
|
size: [200, 100],
|
|
flags: {},
|
|
order: 0,
|
|
mode: 0,
|
|
widgets_values: [30, 12345, 'test prompt']
|
|
}
|
|
|
|
// This would apply values incorrectly without proper ordering
|
|
node.configure(info)
|
|
|
|
// Without fix, values would be applied in wrong order:
|
|
// seed (widget[0]) would get 30 (should be 12345)
|
|
// prompt (widget[1]) would get 12345 (should be 'test prompt')
|
|
// steps (widget[2]) would get 'test prompt' (should be 30)
|
|
|
|
// This test demonstrates the bug - values are applied in wrong order
|
|
expect(node.widgets![0].value).toBe(30) // seed gets steps value (WRONG)
|
|
expect(node.widgets![1].value).toBe(12345) // prompt gets seed value (WRONG)
|
|
expect(node.widgets![2].value).toBe('test prompt') // steps gets prompt value (WRONG)
|
|
})
|
|
|
|
it('should skip widgets with serialize: false', () => {
|
|
node.addWidget('number', 'steps', 20, null, {})
|
|
node.addWidget('button', 'action', 'Click', null, {})
|
|
node.widgets![1].serialize = false // button should not serialize
|
|
node.addWidget('number', 'seed', 0, null, {})
|
|
|
|
const info: ISerialisedNode = {
|
|
id: 1,
|
|
type: 'TestNode',
|
|
pos: [0, 0],
|
|
size: [200, 100],
|
|
flags: {},
|
|
order: 0,
|
|
mode: 0,
|
|
widgets_values: [30, 12345] // Only serializable widgets
|
|
}
|
|
|
|
node.configure(info)
|
|
|
|
expect(node.widgets![0].value).toBe(30) // steps
|
|
expect(node.widgets![1].value).toBe('Click') // button unchanged
|
|
expect(node.widgets![2].value).toBe(12345) // seed
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('sortWidgetValuesByInputOrder', () => {
|
|
it('should reorder widget values based on input_order', () => {
|
|
const inputOrder = ['steps', 'seed', 'prompt']
|
|
const currentWidgetOrder = ['seed', 'prompt', 'steps']
|
|
const widgetValues = [12345, 'test prompt', 30]
|
|
|
|
const reordered = sortWidgetValuesByInputOrder(
|
|
widgetValues,
|
|
currentWidgetOrder,
|
|
inputOrder
|
|
)
|
|
|
|
// Should reorder to match input_order: [steps, seed, prompt]
|
|
expect(reordered).toEqual([30, 12345, 'test prompt'])
|
|
})
|
|
|
|
it('should handle widgets not in input_order', () => {
|
|
const inputOrder = ['steps', 'seed']
|
|
const currentWidgetOrder = ['seed', 'prompt', 'steps', 'cfg']
|
|
const widgetValues = [12345, 'test prompt', 30, 7.5]
|
|
|
|
const reordered = sortWidgetValuesByInputOrder(
|
|
widgetValues,
|
|
currentWidgetOrder,
|
|
inputOrder
|
|
)
|
|
|
|
// Should put ordered items first, then unordered
|
|
expect(reordered).toEqual([30, 12345, 'test prompt', 7.5])
|
|
})
|
|
|
|
it('should handle empty input_order', () => {
|
|
const inputOrder: string[] = []
|
|
const currentWidgetOrder = ['seed', 'prompt', 'steps']
|
|
const widgetValues = [12345, 'test prompt', 30]
|
|
|
|
const reordered = sortWidgetValuesByInputOrder(
|
|
widgetValues,
|
|
currentWidgetOrder,
|
|
inputOrder
|
|
)
|
|
|
|
// Should return values unchanged
|
|
expect(reordered).toEqual([12345, 'test prompt', 30])
|
|
})
|
|
|
|
it('should handle mismatched array lengths', () => {
|
|
const inputOrder = ['steps', 'seed', 'prompt']
|
|
const currentWidgetOrder = ['seed', 'prompt']
|
|
const widgetValues = [12345, 'test prompt', 30] // Extra value
|
|
|
|
const reordered = sortWidgetValuesByInputOrder(
|
|
widgetValues,
|
|
currentWidgetOrder,
|
|
inputOrder
|
|
)
|
|
|
|
// Should handle gracefully, keeping extra values at the end
|
|
// Since 'steps' is not in currentWidgetOrder, it won't be reordered
|
|
// Only 'seed' and 'prompt' will be reordered based on input_order
|
|
expect(reordered).toEqual([12345, 'test prompt', 30])
|
|
})
|
|
})
|