fix: default image input for the template is displayed as empty on dropdown selection

This commit is contained in:
Rizumu Ayaka
2026-01-23 20:02:13 +08:00
parent f647c8f9ee
commit 6f05bbcfcb
2 changed files with 116 additions and 2 deletions

View File

@@ -171,4 +171,87 @@ describe('WidgetSelectDropdown custom label mapping', () => {
expect(Array.isArray(outputItems)).toBe(true)
})
})
describe('missing value handling for template-loaded nodes', () => {
it('creates a fallback item in "all" filter when modelValue is not in available items', () => {
const widget = createMockWidget('template_image.png', {
values: ['img_001.png', 'photo_abc.jpg']
})
const wrapper = mountComponent(widget, 'template_image.png')
const inputItems = wrapper.vm.inputItems
expect(inputItems).toHaveLength(2)
expect(
inputItems.some((item) => item.name === 'template_image.png')
).toBe(false)
// The missing value should be accessible via dropdownItems when filter is 'all' (default)
const dropdownItems = (
wrapper.vm as unknown as { dropdownItems: DropdownItem[] }
).dropdownItems
expect(
dropdownItems.some((item) => item.name === 'template_image.png')
).toBe(true)
expect(dropdownItems[0].name).toBe('template_image.png')
expect(dropdownItems[0].id).toBe('missing-template_image.png')
})
it('does not include fallback item when filter is "inputs" or "outputs"', async () => {
const widget = createMockWidget('template_image.png', {
values: ['img_001.png', 'photo_abc.jpg']
})
const wrapper = mountComponent(widget, 'template_image.png')
// Set filter to 'inputs'
await wrapper.setProps({ filterSelected: 'inputs' } as never)
await wrapper.vm.$nextTick()
const vmWithFilter = wrapper.vm as unknown as {
filterSelected: string
dropdownItems: DropdownItem[]
}
// Manually update filterSelected since it's a model
vmWithFilter.filterSelected = 'inputs'
await wrapper.vm.$nextTick()
// inputItems should not contain the missing value
expect(wrapper.vm.inputItems).toHaveLength(2)
expect(
wrapper.vm.inputItems.every(
(item) => !String(item.id).startsWith('missing-')
)
).toBe(true)
})
it('does not create a fallback item when modelValue exists in available items', () => {
const widget = createMockWidget('img_001.png', {
values: ['img_001.png', 'photo_abc.jpg']
})
const wrapper = mountComponent(widget, 'img_001.png')
const dropdownItems = (
wrapper.vm as unknown as { dropdownItems: DropdownItem[] }
).dropdownItems
expect(dropdownItems).toHaveLength(2)
expect(
dropdownItems.every((item) => !String(item.id).startsWith('missing-'))
).toBe(true)
})
it('does not create a fallback item when modelValue is undefined', () => {
const widget = createMockWidget(undefined as unknown as string, {
values: ['img_001.png', 'photo_abc.jpg']
})
const wrapper = mountComponent(widget, undefined)
const dropdownItems = (
wrapper.vm as unknown as { dropdownItems: DropdownItem[] }
).dropdownItems
expect(dropdownItems).toHaveLength(2)
expect(
dropdownItems.every((item) => !String(item.id).startsWith('missing-'))
).toBe(true)
})
})
})

View File

@@ -146,11 +146,42 @@ const outputItems = computed<DropdownItem[]>(() => {
}))
})
/**
* Creates a fallback item for the current modelValue when it doesn't exist
* in the available items list. This handles cases like template-loaded nodes
* where the saved value may not exist in the current server environment.
*/
const missingValueItem = computed<DropdownItem | null>(() => {
const currentValue = modelValue.value
if (!currentValue) return null
const existsInInputs = inputItems.value.some(
(item) => item.name === currentValue
)
const existsInOutputs = outputItems.value.some(
(item) => item.name === currentValue
)
if (existsInInputs || existsInOutputs) return null
return {
id: `missing-${currentValue}`,
mediaSrc: getMediaUrl(currentValue, 'input'),
name: currentValue,
label: getDisplayLabel(currentValue),
metadata: ''
}
})
const allItems = computed<DropdownItem[]>(() => {
if (props.isAssetMode && assetData) {
return assetData.dropdownItems.value
}
return [...inputItems.value, ...outputItems.value]
const items = [...inputItems.value, ...outputItems.value]
if (missingValueItem.value) {
items.unshift(missingValueItem.value)
}
return items
})
const dropdownItems = computed<DropdownItem[]>(() => {
@@ -165,7 +196,7 @@ const dropdownItems = computed<DropdownItem[]>(() => {
return outputItems.value
case 'all':
default:
return [...inputItems.value, ...outputItems.value]
return allItems.value
}
})