fix(editor): Don't send run data for full manual executions (#12687)

This commit is contained in:
Danny Martini
2025-01-22 15:18:25 +01:00
committed by GitHub
parent 3049cf85a6
commit 9139dc3c29
3 changed files with 81 additions and 43 deletions

View File

@@ -230,28 +230,28 @@ describe('CanvasChat', () => {
// Verify workflow execution // Verify workflow execution
expect(workflowsStore.runWorkflow).toHaveBeenCalledWith( expect(workflowsStore.runWorkflow).toHaveBeenCalledWith(
expect.objectContaining({ expect.objectContaining({
runData: { runData: undefined,
'When chat message received': [ triggerToStartFrom: {
{ name: 'When chat message received',
data: { data: {
main: [ data: {
[ main: [
{ [
json: { {
action: 'sendMessage', json: {
chatInput: 'Hello AI!', action: 'sendMessage',
sessionId: expect.any(String), chatInput: 'Hello AI!',
}, sessionId: expect.any(String),
}, },
], },
], ],
}, ],
executionStatus: 'success',
executionTime: 0,
source: [null],
startTime: expect.any(Number),
}, },
], executionStatus: 'success',
executionTime: 0,
source: [null],
startTime: expect.any(Number),
},
}, },
}), }),
); );

View File

@@ -21,7 +21,7 @@ import { useToast } from './useToast';
import { useI18n } from '@/composables/useI18n'; import { useI18n } from '@/composables/useI18n';
import { useLocalStorage } from '@vueuse/core'; import { useLocalStorage } from '@vueuse/core';
import { ref } from 'vue'; import { ref } from 'vue';
import { mock } from 'vitest-mock-extended'; import { captor, mock } from 'vitest-mock-extended';
vi.mock('@/stores/workflows.store', () => ({ vi.mock('@/stores/workflows.store', () => ({
useWorkflowsStore: vi.fn().mockReturnValue({ useWorkflowsStore: vi.fn().mockReturnValue({
@@ -409,27 +409,28 @@ describe('useRunWorkflow({ router })', () => {
const mockExecutionResponse = { executionId: '123' }; const mockExecutionResponse = { executionId: '123' };
const mockRunData = { nodeName: [] }; const mockRunData = { nodeName: [] };
const { runWorkflow } = useRunWorkflow({ router }); const { runWorkflow } = useRunWorkflow({ router });
const dataCaptor = captor();
const workflow = mock<Workflow>({ name: 'Test Workflow' });
workflow.getParentNodes.mockReturnValue([]);
vi.mocked(useLocalStorage).mockReturnValueOnce(ref(0)); vi.mocked(useLocalStorage).mockReturnValueOnce(ref(0));
vi.mocked(rootStore).pushConnectionActive = true; vi.mocked(rootStore).pushConnectionActive = true;
vi.mocked(workflowsStore).runWorkflow.mockResolvedValue(mockExecutionResponse); vi.mocked(workflowsStore).runWorkflow.mockResolvedValue(mockExecutionResponse);
vi.mocked(workflowsStore).nodesIssuesExist = false; vi.mocked(workflowsStore).nodesIssuesExist = false;
vi.mocked(workflowHelpers).getCurrentWorkflow.mockReturnValue({ vi.mocked(workflowHelpers).getCurrentWorkflow.mockReturnValue(workflow);
name: 'Test Workflow', vi.mocked(workflowHelpers).getWorkflowDataToSave.mockResolvedValue(
} as Workflow); mock<IWorkflowData>({ id: 'workflowId', nodes: [] }),
vi.mocked(workflowHelpers).getWorkflowDataToSave.mockResolvedValue({ );
id: 'workflowId',
nodes: [],
} as unknown as IWorkflowData);
vi.mocked(workflowsStore).getWorkflowRunData = mockRunData; vi.mocked(workflowsStore).getWorkflowRunData = mockRunData;
// ACT // ACT
const result = await runWorkflow({}); const result = await runWorkflow({ destinationNode: 'some node name' });
// ASSERT // ASSERT
expect(result).toEqual(mockExecutionResponse); expect(result).toEqual(mockExecutionResponse);
expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledTimes(1); expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledTimes(1);
expect(vi.mocked(workflowsStore.setWorkflowExecutionData).mock.calls[0][0]).toMatchObject({ expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledWith(dataCaptor);
expect(dataCaptor.value).toMatchObject({
data: { resultData: { runData: {} } }, data: { resultData: { runData: {} } },
}); });
}); });
@@ -439,18 +440,47 @@ describe('useRunWorkflow({ router })', () => {
const mockExecutionResponse = { executionId: '123' }; const mockExecutionResponse = { executionId: '123' };
const mockRunData = { nodeName: [] }; const mockRunData = { nodeName: [] };
const { runWorkflow } = useRunWorkflow({ router }); const { runWorkflow } = useRunWorkflow({ router });
const dataCaptor = captor();
const workflow = mock<Workflow>({ name: 'Test Workflow' });
workflow.getParentNodes.mockReturnValue([]);
vi.mocked(useLocalStorage).mockReturnValueOnce(ref(1)); vi.mocked(useLocalStorage).mockReturnValueOnce(ref(1));
vi.mocked(rootStore).pushConnectionActive = true; vi.mocked(rootStore).pushConnectionActive = true;
vi.mocked(workflowsStore).runWorkflow.mockResolvedValue(mockExecutionResponse); vi.mocked(workflowsStore).runWorkflow.mockResolvedValue(mockExecutionResponse);
vi.mocked(workflowsStore).nodesIssuesExist = false; vi.mocked(workflowsStore).nodesIssuesExist = false;
vi.mocked(workflowHelpers).getCurrentWorkflow.mockReturnValue({ vi.mocked(workflowHelpers).getCurrentWorkflow.mockReturnValue(workflow);
name: 'Test Workflow', vi.mocked(workflowHelpers).getWorkflowDataToSave.mockResolvedValue(
} as Workflow); mock<IWorkflowData>({ id: 'workflowId', nodes: [] }),
vi.mocked(workflowHelpers).getWorkflowDataToSave.mockResolvedValue({ );
id: 'workflowId', vi.mocked(workflowsStore).getWorkflowRunData = mockRunData;
nodes: [],
} as unknown as IWorkflowData); // ACT
const result = await runWorkflow({ destinationNode: 'some node name' });
// ASSERT
expect(result).toEqual(mockExecutionResponse);
expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledTimes(1);
expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledWith(dataCaptor);
expect(dataCaptor.value).toMatchObject({ data: { resultData: { runData: mockRunData } } });
});
it("does not send run data if it's not a partial execution even if `PartialExecution.version` is set to 1", async () => {
// ARRANGE
const mockExecutionResponse = { executionId: '123' };
const mockRunData = { nodeName: [] };
const { runWorkflow } = useRunWorkflow({ router });
const dataCaptor = captor();
const workflow = mock<Workflow>({ name: 'Test Workflow' });
workflow.getParentNodes.mockReturnValue([]);
vi.mocked(useLocalStorage).mockReturnValueOnce(ref(1));
vi.mocked(rootStore).pushConnectionActive = true;
vi.mocked(workflowsStore).runWorkflow.mockResolvedValue(mockExecutionResponse);
vi.mocked(workflowsStore).nodesIssuesExist = false;
vi.mocked(workflowHelpers).getCurrentWorkflow.mockReturnValue(workflow);
vi.mocked(workflowHelpers).getWorkflowDataToSave.mockResolvedValue(
mock<IWorkflowData>({ id: 'workflowId', nodes: [] }),
);
vi.mocked(workflowsStore).getWorkflowRunData = mockRunData; vi.mocked(workflowsStore).getWorkflowRunData = mockRunData;
// ACT // ACT
@@ -458,10 +488,9 @@ describe('useRunWorkflow({ router })', () => {
// ASSERT // ASSERT
expect(result).toEqual(mockExecutionResponse); expect(result).toEqual(mockExecutionResponse);
expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledTimes(1); expect(workflowsStore.runWorkflow).toHaveBeenCalledTimes(1);
expect(vi.mocked(workflowsStore.setWorkflowExecutionData).mock.calls[0][0]).toMatchObject({ expect(workflowsStore.runWorkflow).toHaveBeenCalledWith(dataCaptor);
data: { resultData: { runData: mockRunData } }, expect(dataCaptor.value).toHaveProperty('runData', undefined);
});
}); });
}); });

View File

@@ -264,14 +264,23 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
// 0 is the old flow // 0 is the old flow
// 1 is the new flow // 1 is the new flow
const partialExecutionVersion = useLocalStorage('PartialExecution.version', -1); const partialExecutionVersion = useLocalStorage('PartialExecution.version', -1);
// partial executions must have a destination node
const isPartialExecution = options.destinationNode !== undefined;
const startRunData: IStartRunData = { const startRunData: IStartRunData = {
workflowData, workflowData,
// With the new partial execution version the backend decides what run runData: !isPartialExecution
// data to use and what to ignore. ? // if it's a full execution we don't want to send any run data
runData: partialExecutionVersion.value === 1 ? (runData ?? undefined) : newRunData, undefined
: partialExecutionVersion.value === 1
? // With the new partial execution version the backend decides
//what run data to use and what to ignore.
(runData ?? undefined)
: // for v0 we send the run data the FE constructed
newRunData,
startNodes, startNodes,
triggerToStartFrom, triggerToStartFrom,
}; };
if ('destinationNode' in options) { if ('destinationNode' in options) {
startRunData.destinationNode = options.destinationNode; startRunData.destinationNode = options.destinationNode;
} }