Compare commits

..

1 Commits

Author SHA1 Message Date
CodeRabbit Fixer
461bea6d99 fix: refactor: create rename-aware detach/attach helper in workflowStore to avoid duplicate mutation paths (#9407)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:34:12 +01:00
2 changed files with 8 additions and 72 deletions

View File

@@ -121,68 +121,6 @@ describe('resolveSubgraphInputLink', () => {
expect(result).toBe('seed_input')
})
test('skips broken links where getLink returns undefined', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('prompt')
addLinkedInteriorInput(subgraph, 'prompt', 'valid_input', 'valid')
const broken = addLinkedInteriorInput(
subgraph,
'prompt',
'broken_input',
'broken'
)
const originalGetLink = subgraph.getLink.bind(subgraph)
vi.spyOn(subgraph, 'getLink').mockImplementation((linkId) => {
if (typeof linkId !== 'number') return originalGetLink(linkId)
if (linkId === broken.linkId) return undefined
return originalGetLink(linkId)
})
const result = resolveSubgraphInputLink(
subgraphNode,
'prompt',
({ targetInput }) => targetInput.name
)
expect(result).toBe('valid_input')
})
test('returns result from latest connection when multiple links resolve', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('prompt')
addLinkedInteriorInput(subgraph, 'prompt', 'older_input', 'older')
addLinkedInteriorInput(subgraph, 'prompt', 'newer_input', 'newer')
const result = resolveSubgraphInputLink(
subgraphNode,
'prompt',
({ targetInput }) => targetInput.name
)
expect(result).toBe('newer_input')
})
test('falls back to earlier link when latest resolve callback returns undefined', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('prompt')
addLinkedInteriorInput(subgraph, 'prompt', 'fallback_input', 'fallback')
const newer = addLinkedInteriorInput(
subgraph,
'prompt',
'skipped_input',
'skipped'
)
const result = resolveSubgraphInputLink(
subgraphNode,
'prompt',
({ targetInput }) => {
if (targetInput.link === newer.linkId) return undefined
return targetInput.name
}
)
expect(result).toBe('fallback_input')
})
test('caches getTargetWidget result within the same callback evaluation', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('model')
const linked = addLinkedInteriorInput(

View File

@@ -103,14 +103,16 @@ export const useWorkflowStore = defineStore('workflow', () => {
/**
* Detach the workflow from the store. lightweight helper function.
* @param workflow The workflow to detach.
* @param oldPath Optional previous path to detach from (used during rename when workflow.path has already changed).
* @returns The index of the workflow in the openWorkflowPaths array, or -1 if the workflow was not open.
*/
const detachWorkflow = (workflow: ComfyWorkflow) => {
delete workflowLookup.value[workflow.path]
const index = openWorkflowPaths.value.indexOf(workflow.path)
const detachWorkflow = (workflow: ComfyWorkflow, oldPath?: string) => {
const path = oldPath ?? workflow.path
delete workflowLookup.value[path]
const index = openWorkflowPaths.value.indexOf(path)
if (index !== -1) {
openWorkflowPaths.value = openWorkflowPaths.value.filter(
(path) => path !== workflow.path
(p) => p !== path
)
}
return index
@@ -501,12 +503,8 @@ export const useWorkflowStore = defineStore('workflow', () => {
// Synchronously swap old path for new path in lookup and open paths
// to avoid a tab flicker caused by an async gap between detach/attach.
delete workflowLookup.value[oldPath]
workflowLookup.value[workflow.path] = workflow
const openIndex = openWorkflowPaths.value.indexOf(oldPath)
if (openIndex !== -1) {
openWorkflowPaths.value.splice(openIndex, 1, workflow.path)
}
const openIndex = detachWorkflow(workflow, oldPath)
attachWorkflow(workflow, openIndex)
draftStore.moveDraft(oldPath, newPath, workflow.key)