mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-15 19:54:32 +00:00
fix: address review feedback for refreshComboInNode
- Distinguish 'no result' (undefined) from 'empty options' ([]) so a legitimate empty combo list propagates to the widget instead of being treated as a no-op. - Fall back to input.name when the connected target's input has no widget locator, mirroring _onFirstConnection. - Add regression tests for V2 combo specs, empty option propagation, and the widgetless-input fallback path.
This commit is contained in:
@@ -122,6 +122,18 @@ function defsWithCombo(
|
||||
}
|
||||
}
|
||||
|
||||
function defsWithV2Combo(
|
||||
values: (string | number)[]
|
||||
): Record<string, ComfyNodeDef> {
|
||||
return {
|
||||
[TARGET_NODE_TYPE]: fromPartial<ComfyNodeDef>({
|
||||
input: {
|
||||
required: { [TARGET_INPUT_NAME]: ['COMBO', { options: values }] }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
describe('PrimitiveNode.refreshComboInNode', () => {
|
||||
it('updates combo options from the freshly passed defs', () => {
|
||||
const widget = createComboWidget('euler', ORIGINAL_OPTIONS)
|
||||
@@ -196,6 +208,49 @@ describe('PrimitiveNode.refreshComboInNode', () => {
|
||||
expect(widget.callback).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('updates combo options from V2 combo specs in defs', () => {
|
||||
const widget = createComboWidget('euler', ORIGINAL_OPTIONS)
|
||||
const stub = createPrimitiveStub({
|
||||
widget,
|
||||
slotWidget: createSlotWidget([ORIGINAL_OPTIONS, {}])
|
||||
})
|
||||
|
||||
refreshOnStub(stub, defsWithV2Combo(FRESH_OPTIONS))
|
||||
|
||||
expect(widget.options.values).toEqual(FRESH_OPTIONS)
|
||||
})
|
||||
|
||||
it('propagates an empty option list when defs return one', () => {
|
||||
const widget = createComboWidget('euler', ORIGINAL_OPTIONS)
|
||||
const stub = createPrimitiveStub({
|
||||
widget,
|
||||
slotWidget: createSlotWidget([ORIGINAL_OPTIONS, {}])
|
||||
})
|
||||
|
||||
refreshOnStub(stub, defsWithCombo([]))
|
||||
|
||||
expect(widget.options.values).toEqual([])
|
||||
expect(widget.value).toBeUndefined()
|
||||
})
|
||||
|
||||
it('falls back to input.name when the target input has no widget locator', () => {
|
||||
const widget = createComboWidget('euler', [])
|
||||
const targetNode = fromPartial<TargetNode>({
|
||||
id: 9,
|
||||
type: TARGET_NODE_TYPE,
|
||||
inputs: [
|
||||
fromPartial<INodeInputSlot>({
|
||||
name: TARGET_INPUT_NAME
|
||||
})
|
||||
]
|
||||
})
|
||||
const stub = createPrimitiveStub({ widget, targetNode })
|
||||
|
||||
refreshOnStub(stub, defsWithCombo(FRESH_OPTIONS))
|
||||
|
||||
expect(widget.options.values).toEqual(FRESH_OPTIONS)
|
||||
})
|
||||
|
||||
it('skips non-combo widgets', () => {
|
||||
const widget = fromPartial<IBaseWidget>({
|
||||
type: 'string',
|
||||
|
||||
@@ -64,7 +64,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
if (widget?.type !== 'combo') return
|
||||
|
||||
const newValues = this._resolveComboValues(defs)
|
||||
if (!newValues?.length) return
|
||||
if (newValues === undefined) return
|
||||
|
||||
widget.options.values = newValues
|
||||
|
||||
@@ -78,17 +78,15 @@ export class PrimitiveNode extends LGraphNode {
|
||||
defs?: Record<string, ComfyNodeDef>
|
||||
): (string | number)[] | undefined {
|
||||
const fromDefs = defs ? this._comboValuesFromDefs(defs) : undefined
|
||||
if (fromDefs?.length) return fromDefs
|
||||
if (fromDefs !== undefined) return fromDefs
|
||||
|
||||
const slotWidget = this.outputs?.[0]?.widget
|
||||
const config = (
|
||||
slotWidget?.[GET_CONFIG] as (() => InputSpec) | undefined
|
||||
)?.()
|
||||
if (!config) return undefined
|
||||
if (!config || !isComboInputSpec(config)) return undefined
|
||||
|
||||
return isComboInputSpec(config)
|
||||
? getComboSpecComboOptions(config)
|
||||
: undefined
|
||||
return getComboSpecComboOptions(config)
|
||||
}
|
||||
|
||||
private _comboValuesFromDefs(
|
||||
@@ -102,12 +100,12 @@ export class PrimitiveNode extends LGraphNode {
|
||||
if (!targetType) return undefined
|
||||
|
||||
const targetInput = targetNode?.inputs?.[link.target_slot]
|
||||
const widgetName = targetInput?.widget?.name
|
||||
if (!widgetName) return undefined
|
||||
const inputName = targetInput?.widget?.name ?? targetInput?.name
|
||||
if (!inputName) return undefined
|
||||
|
||||
const def = defs[targetType]
|
||||
const inputSpec =
|
||||
def?.input?.required?.[widgetName] ?? def?.input?.optional?.[widgetName]
|
||||
def?.input?.required?.[inputName] ?? def?.input?.optional?.[inputName]
|
||||
if (!inputSpec || !isComboInputSpec(inputSpec)) return undefined
|
||||
|
||||
return getComboSpecComboOptions(inputSpec)
|
||||
|
||||
Reference in New Issue
Block a user