From e4f1950af575cfc5998ada65cd78b1b5330e3c23 Mon Sep 17 00:00:00 2001 From: Comfy Org PR Bot Date: Sun, 1 Feb 2026 16:40:30 +0900 Subject: [PATCH] [backport core/1.38] fix: update reactive ref after merge in imagePreviewStore (#8502) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport of #8479 to `core/1.38` Automatically created by backport workflow. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8502-backport-core-1-38-fix-update-reactive-ref-after-merge-in-imagePreviewStore-2f96d73d3650815f944cc401a8c2d264) by [Unito](https://www.unito.io) --------- Co-authored-by: Christian Byrne Co-authored-by: Amp Co-authored-by: Austin Mroz --- src/stores/imagePreviewStore.test.ts | 61 +++++++++++++++++++++++++++- src/stores/imagePreviewStore.ts | 1 + 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/stores/imagePreviewStore.test.ts b/src/stores/imagePreviewStore.test.ts index d2bb8d639..73bbde3cb 100644 --- a/src/stores/imagePreviewStore.test.ts +++ b/src/stores/imagePreviewStore.test.ts @@ -1,3 +1,4 @@ +import { createTestingPinia } from '@pinia/testing' import { createPinia, setActivePinia } from 'pinia' import { beforeEach, describe, expect, it, vi } from 'vitest' @@ -13,7 +14,9 @@ vi.mock('@/utils/litegraphUtil', () => ({ vi.mock('@/scripts/app', () => ({ app: { - getPreviewFormatParam: vi.fn(() => '&format=test_webp') + getPreviewFormatParam: vi.fn(() => '&format=test_webp'), + nodeOutputs: {} as Record, + nodePreviewImages: {} as Record } })) @@ -28,6 +31,62 @@ const createMockOutputs = ( images?: ExecutedWsMessage['output']['images'] ): ExecutedWsMessage['output'] => ({ images }) +vi.mock('@/stores/executionStore', () => ({ + useExecutionStore: vi.fn(() => ({ + executionIdToNodeLocatorId: vi.fn((id: string) => id) + })) +})) + +vi.mock('@/platform/workflow/management/stores/workflowStore', () => ({ + useWorkflowStore: vi.fn(() => ({ + nodeIdToNodeLocatorId: vi.fn((id: string | number) => String(id)), + nodeToNodeLocatorId: vi.fn((node: { id: number }) => String(node.id)) + })) +})) + +describe('imagePreviewStore setNodeOutputsByExecutionId with merge', () => { + beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) + vi.clearAllMocks() + app.nodeOutputs = {} + app.nodePreviewImages = {} + }) + + it('should update reactive nodeOutputs.value when merging outputs', () => { + const store = useNodeOutputStore() + const executionId = '1' + + const initialOutput = createMockOutputs([{ filename: 'a.png' }]) + store.setNodeOutputsByExecutionId(executionId, initialOutput) + + expect(app.nodeOutputs[executionId]?.images).toHaveLength(1) + expect(store.nodeOutputs[executionId]?.images).toHaveLength(1) + + const newOutput = createMockOutputs([{ filename: 'b.png' }]) + store.setNodeOutputsByExecutionId(executionId, newOutput, { merge: true }) + + expect(app.nodeOutputs[executionId]?.images).toHaveLength(2) + expect(store.nodeOutputs[executionId]?.images).toHaveLength(2) + }) + + it('should assign to reactive ref after merge for Vue reactivity', () => { + const store = useNodeOutputStore() + const executionId = '1' + + const initialOutput = createMockOutputs([{ filename: 'a.png' }]) + store.setNodeOutputsByExecutionId(executionId, initialOutput) + + const newOutput = createMockOutputs([{ filename: 'b.png' }]) + + store.setNodeOutputsByExecutionId(executionId, newOutput, { merge: true }) + + expect(store.nodeOutputs[executionId]).toStrictEqual( + app.nodeOutputs[executionId] + ) + expect(store.nodeOutputs[executionId]?.images).toHaveLength(2) + }) +}) + describe('imagePreviewStore getPreviewParam', () => { beforeEach(() => { setActivePinia(createPinia()) diff --git a/src/stores/imagePreviewStore.ts b/src/stores/imagePreviewStore.ts index db2c9abaa..d2aa2d4e0 100644 --- a/src/stores/imagePreviewStore.ts +++ b/src/stores/imagePreviewStore.ts @@ -148,6 +148,7 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => { existingOutput[k] = newValue } } + nodeOutputs.value[nodeLocatorId] = existingOutput return } }