fix(editor): Fix pin data showing up in production executions on new canvas (#11951)

This commit is contained in:
Alex Grozav 2024-11-29 12:02:16 +02:00 committed by GitHub
parent 40a7445f08
commit 5f6f8a1bdd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 99 additions and 20 deletions

View file

@ -5,12 +5,13 @@ import type {
IWebhookDescription,
Workflow,
INodeConnections,
WorkflowExecuteMode,
} from 'n8n-workflow';
import { NodeConnectionType, NodeHelpers } from 'n8n-workflow';
import { useCanvasOperations } from '@/composables/useCanvasOperations';
import type { CanvasConnection, CanvasNode } from '@/types';
import { CanvasConnectionMode } from '@/types';
import type { ICredentialsResponse, INodeUi, IWorkflowDb } from '@/Interface';
import type { ICredentialsResponse, IExecutionResponse, INodeUi, IWorkflowDb } from '@/Interface';
import { RemoveNodeCommand } from '@/models/history';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useUIStore } from '@/stores/ui.store';
@ -2174,6 +2175,67 @@ describe('useCanvasOperations', () => {
});
});
});
describe('openExecution', () => {
it('should initialize workspace and set execution data when execution is found', async () => {
const workflowsStore = mockedStore(useWorkflowsStore);
const uiStore = mockedStore(useUIStore);
const { openExecution } = useCanvasOperations({ router });
const executionId = '123';
const executionData: IExecutionResponse = {
id: executionId,
finished: true,
status: 'success',
startedAt: new Date(),
createdAt: new Date(),
workflowData: createTestWorkflow(),
mode: 'manual' as WorkflowExecuteMode,
};
workflowsStore.getExecution.mockResolvedValue(executionData);
const result = await openExecution(executionId);
expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledWith(executionData);
expect(uiStore.stateIsDirty).toBe(false);
expect(result).toEqual(executionData);
});
it('should throw error when execution data is undefined', async () => {
const workflowsStore = mockedStore(useWorkflowsStore);
const executionId = '123';
const { openExecution } = useCanvasOperations({ router });
workflowsStore.getExecution.mockResolvedValue(undefined);
await expect(openExecution(executionId)).rejects.toThrow(
`Execution with id "${executionId}" could not be found!`,
);
});
it('should clear workflow pin data if execution mode is not manual', async () => {
const workflowsStore = mockedStore(useWorkflowsStore);
const { openExecution } = useCanvasOperations({ router });
const executionId = '123';
const executionData: IExecutionResponse = {
id: executionId,
finished: true,
status: 'success',
startedAt: new Date(),
createdAt: new Date(),
workflowData: createTestWorkflow(),
mode: 'trigger' as WorkflowExecuteMode,
};
workflowsStore.getExecution.mockResolvedValue(executionData);
await openExecution(executionId);
expect(workflowsStore.setWorkflowPinData).toHaveBeenCalledWith({});
});
});
});
function buildImportNodes() {

View file

@ -5,6 +5,7 @@
import type {
AddedNodesAndConnections,
IExecutionResponse,
INodeUi,
ITag,
IUsedCredential,
@ -1849,6 +1850,32 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
deleteNodes(ids);
}
async function openExecution(executionId: string) {
let data: IExecutionResponse | undefined;
try {
data = await workflowsStore.getExecution(executionId);
} catch (error) {
toast.showError(error, i18n.baseText('nodeView.showError.openExecution.title'));
return;
}
if (data === undefined) {
throw new Error(`Execution with id "${executionId}" could not be found!`);
}
initializeWorkspace(data.workflowData);
workflowsStore.setWorkflowExecutionData(data);
if (data.mode !== 'manual') {
workflowsStore.setWorkflowPinData({});
}
uiStore.stateIsDirty = false;
return data;
}
return {
lastClickPosition,
editableWorkflow,
@ -1891,5 +1918,6 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
resetWorkspace,
initializeWorkspace,
resolveNodeWebhook,
openExecution,
};
}

View file

@ -185,6 +185,7 @@ const {
fetchWorkflowDataFromUrl,
resetWorkspace,
initializeWorkspace,
openExecution,
editableWorkflow,
editableWorkflowObject,
lastClickPosition,
@ -1051,30 +1052,18 @@ function trackRunWorkflowToNode(node: INodeUi) {
void externalHooks.run('nodeView.onRunNode', telemetryPayload);
}
async function openExecution(executionId: string) {
async function onOpenExecution(executionId: string) {
canvasStore.startLoading();
resetWorkspace();
let data: IExecutionResponse | undefined;
try {
data = await workflowsStore.getExecution(executionId);
} catch (error) {
toast.showError(error, i18n.baseText('nodeView.showError.openExecution.title'));
return;
}
if (data === undefined) {
throw new Error(`Execution with id "${executionId}" could not be found!`);
}
await initializeData();
initializeWorkspace(data.workflowData);
const data = await openExecution(executionId);
if (!data) {
return;
}
workflowsStore.setWorkflowExecutionData(data);
uiStore.stateIsDirty = false;
canvasStore.stopLoading();
fitView();
canvasEventBus.emit('open:execution', data);
@ -1320,7 +1309,7 @@ async function onPostMessageReceived(messageEvent: MessageEvent) {
// so everything it needs has to be sent using post messages and passed down to child components
isProductionExecutionPreview.value = json.executionMode !== 'manual';
await openExecution(json.executionId);
await onOpenExecution(json.executionId);
canOpenNDV.value = json.canOpenNDV ?? true;
hideNodeIssues.value = json.hideNodeIssues ?? false;
isExecutionPreview.value = true;