From b91219ea15fdc5e1960fb53a6b0228ce9ec00c5b Mon Sep 17 00:00:00 2001 From: Daria Date: Thu, 11 Sep 2025 15:29:41 +0300 Subject: [PATCH] fix(editor): Set workflow name when importing (no-changelog) (#19410) --- cypress/e2e/17-sharing.cy.ts | 4 +-- cypress/e2e/19-execution.cy.ts | 2 +- cypress/e2e/20-workflow-executions.cy.ts | 2 +- .../e2e/30-editor-after-route-changes.cy.ts | 2 +- cypress/e2e/32-node-io-filter.cy.ts | 2 +- cypress/e2e/44-routing.cy.ts | 10 +++---- .../e2e/45-workflow-selector-parameter.cy.ts | 4 +-- cypress/support/commands.ts | 24 +++++++---------- cypress/support/index.ts | 3 +-- .../composables/useCanvasOperations.test.ts | 26 +++++++++++++++++++ .../src/composables/useCanvasOperations.ts | 4 +++ 11 files changed, 53 insertions(+), 30 deletions(-) diff --git a/cypress/e2e/17-sharing.cy.ts b/cypress/e2e/17-sharing.cy.ts index 6aa8b64e7e..ea26cdb9b3 100644 --- a/cypress/e2e/17-sharing.cy.ts +++ b/cypress/e2e/17-sharing.cy.ts @@ -62,8 +62,8 @@ describe('Sharing', { disableAutoLogin: true }, () => { cy.visit(workflowsPage.url); workflowsPage.getters.createWorkflowButton().click(); - cy.createFixtureWorkflow('Test_workflow_1.json', 'Workflow W2'); - workflowPage.actions.saveWorkflowOnButtonClick(); + cy.createFixtureWorkflow('Test_workflow_1.json'); + workflowPage.actions.setWorkflowName('Workflow W2'); cy.url().then((url) => { workflowW2Url = url; }); diff --git a/cypress/e2e/19-execution.cy.ts b/cypress/e2e/19-execution.cy.ts index d88cf55c90..ec9f3fd42a 100644 --- a/cypress/e2e/19-execution.cy.ts +++ b/cypress/e2e/19-execution.cy.ts @@ -466,7 +466,7 @@ describe('Execution', () => { }); it('should send proper payload for node rerun', () => { - cy.createFixtureWorkflow('Multiple_trigger_node_rerun.json', 'Multiple trigger node rerun'); + cy.createFixtureWorkflow('Multiple_trigger_node_rerun.json'); workflowPage.getters.zoomToFitButton().click(); workflowPage.getters.executeWorkflowButton().click(); diff --git a/cypress/e2e/20-workflow-executions.cy.ts b/cypress/e2e/20-workflow-executions.cy.ts index eb0129ba33..7a2f1e6c03 100644 --- a/cypress/e2e/20-workflow-executions.cy.ts +++ b/cypress/e2e/20-workflow-executions.cy.ts @@ -14,7 +14,7 @@ describe('Workflow Executions', () => { describe('when workflow is saved', () => { beforeEach(() => { workflowPage.actions.visit(); - cy.createFixtureWorkflow('Test_workflow_4_executions_view.json', 'My test workflow'); + cy.createFixtureWorkflow('Test_workflow_4_executions_view.json'); }); it('should render executions tab correctly', () => { diff --git a/cypress/e2e/30-editor-after-route-changes.cy.ts b/cypress/e2e/30-editor-after-route-changes.cy.ts index 4313c5fdec..cdd550b000 100644 --- a/cypress/e2e/30-editor-after-route-changes.cy.ts +++ b/cypress/e2e/30-editor-after-route-changes.cy.ts @@ -43,7 +43,7 @@ describe('Editor zoom should work after route changes', () => { cy.enableFeature('workflowHistory'); cy.signinAsOwner(); workflowPage.actions.visit(); - cy.createFixtureWorkflow('Lots_of_nodes.json', 'Lots of nodes'); + cy.createFixtureWorkflow('Lots_of_nodes.json'); workflowPage.actions.saveWorkflowOnButtonClick(); }); diff --git a/cypress/e2e/32-node-io-filter.cy.ts b/cypress/e2e/32-node-io-filter.cy.ts index 6613fa1ff2..54a2df677a 100644 --- a/cypress/e2e/32-node-io-filter.cy.ts +++ b/cypress/e2e/32-node-io-filter.cy.ts @@ -6,7 +6,7 @@ const ndv = new NDV(); describe('Node IO Filter', () => { beforeEach(() => { workflowPage.actions.visit(); - cy.createFixtureWorkflow('Node_IO_filter.json', 'Node IO filter'); + cy.createFixtureWorkflow('Node_IO_filter.json'); workflowPage.actions.saveWorkflowOnButtonClick(); workflowPage.actions.executeWorkflow(); }); diff --git a/cypress/e2e/44-routing.cy.ts b/cypress/e2e/44-routing.cy.ts index 723ca57409..d01981ae18 100644 --- a/cypress/e2e/44-routing.cy.ts +++ b/cypress/e2e/44-routing.cy.ts @@ -24,7 +24,7 @@ describe('Workflows', () => { getNewWorkflowCardButton().should('be.visible'); getNewWorkflowCardButton().click(); - cy.createFixtureWorkflow('Test_workflow_1.json', 'Empty State Card Workflow'); + cy.createFixtureWorkflow('Test_workflow_1.json'); addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME); @@ -43,7 +43,7 @@ describe('Workflows', () => { it('should correct route after cancelling saveChangesModal', () => { getCreateWorkflowButton().click(); - cy.createFixtureWorkflow('Test_workflow_1.json', 'Empty State Card Workflow'); + cy.createFixtureWorkflow('Test_workflow_1.json'); addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true, true); // Here we go back via browser rather than the home button @@ -63,7 +63,7 @@ describe('Workflows', () => { getCreateWorkflowButton().click(); saveWorkflowOnButtonClick(); cy.url().then((startUrl) => { - cy.createFixtureWorkflow('Test_workflow_1.json', 'Empty State Card Workflow'); + cy.createFixtureWorkflow('Test_workflow_1.json'); cy.url().should('equal', startUrl); addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true, true); @@ -80,7 +80,7 @@ describe('Workflows', () => { it('should open ndv via URL', () => { getCreateWorkflowButton().click(); saveWorkflowOnButtonClick(); - cy.createFixtureWorkflow('Test_workflow_1.json', 'Empty State Card Workflow'); + cy.createFixtureWorkflow('Test_workflow_1.json'); addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true, true); cy.url().then((ndvUrl) => { @@ -98,7 +98,7 @@ describe('Workflows', () => { it('should open show warning and drop nodeId from URL if it contained an unknown nodeId', () => { getCreateWorkflowButton().click(); saveWorkflowOnButtonClick(); - cy.createFixtureWorkflow('Test_workflow_1.json', 'Empty State Card Workflow'); + cy.createFixtureWorkflow('Test_workflow_1.json'); addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true, true); cy.url().then((ndvUrl) => { diff --git a/cypress/e2e/45-workflow-selector-parameter.cy.ts b/cypress/e2e/45-workflow-selector-parameter.cy.ts index f307b37c99..a739062d23 100644 --- a/cypress/e2e/45-workflow-selector-parameter.cy.ts +++ b/cypress/e2e/45-workflow-selector-parameter.cy.ts @@ -11,8 +11,8 @@ describe('Workflow Selector Parameter', () => { cy.signinAsOwner(); ['Get_Weather', 'Search_DB'].forEach((workflowName) => { workflowPage.actions.visit(); - cy.createFixtureWorkflow(`Test_Subworkflow_${workflowName}.json`, workflowName); - workflowPage.actions.saveWorkflowOnButtonClick(); + cy.createFixtureWorkflow(`Test_Subworkflow_${workflowName}.json`); + workflowPage.actions.setWorkflowName(workflowName); }); workflowPage.actions.visit(); workflowPage.actions.addInitialNodeToCanvas(EXECUTE_WORKFLOW_NODE_NAME, { diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 361b0c0e06..735a2fe720 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -10,7 +10,6 @@ import { N8N_AUTH_COOKIE, } from '../constants'; import { WorkflowPage } from '../pages'; -import { getUniqueWorkflowName } from '../utils/workflowUtils'; Cypress.Commands.add('setAppDate', (targetDate: number | Date) => { cy.window().then((win) => { @@ -26,22 +25,17 @@ Cypress.Commands.add('getByTestId', (selector, ...args) => { return cy.get(`[data-test-id="${selector}"]`, ...args); }); -Cypress.Commands.add( - 'createFixtureWorkflow', - (fixtureKey: string, workflowName = getUniqueWorkflowName()) => { - const workflowPage = new WorkflowPage(); +Cypress.Commands.add('createFixtureWorkflow', (fixtureKey: string) => { + const workflowPage = new WorkflowPage(); - // We need to force the click because the input is hidden - workflowPage.getters - .workflowImportInput() - .selectFile(`fixtures/${fixtureKey}`, { force: true }); + // We need to force the click because the input is hidden + workflowPage.getters.workflowImportInput().selectFile(`fixtures/${fixtureKey}`, { force: true }); - cy.waitForLoad(false); - workflowPage.actions.setWorkflowName(workflowName); - workflowPage.getters.saveButton().should('contain', 'Saved'); - workflowPage.actions.zoomToFit(); - }, -); + cy.waitForLoad(false); + workflowPage.actions.saveWorkflowOnButtonClick(); + workflowPage.getters.saveButton().should('contain', 'Saved'); + workflowPage.actions.zoomToFit(); +}); Cypress.Commands.addQuery('findChildByTestId', function (testId: string) { return (subject: Cypress.Chainable) => subject.find(`[data-test-id="${testId}"]`); diff --git a/cypress/support/index.ts b/cypress/support/index.ts index 0c428851d0..322a421d2a 100644 --- a/cypress/support/index.ts +++ b/cypress/support/index.ts @@ -33,9 +33,8 @@ declare global { * Creates a workflow from the given fixture and optionally renames it. * * @param fixtureKey - * @param [workflowName] Optional name for the workflow. A random nanoid is used if not given */ - createFixtureWorkflow(fixtureKey: string, workflowName?: string): void; + createFixtureWorkflow(fixtureKey: string): void; /** @deprecated use signinAsOwner, signinAsAdmin or signinAsMember instead */ signin(payload: SigninPayload): void; signinAsOwner(): void; diff --git a/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts b/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts index a67253c3a5..642f6562c4 100644 --- a/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts +++ b/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts @@ -3571,6 +3571,32 @@ describe('useCanvasOperations', () => { // Ensure no telemetry was called at all expect(telemetry.track).not.toHaveBeenCalled(); }); + + it('should set workflow name when importing with name', async () => { + const workflowsStore = mockedStore(useWorkflowsStore); + + // This mock is needed for addImportedNodesToWorkflow to work + workflowsStore.createWorkflowObject = vi.fn().mockReturnValue({ + nodes: {}, + connections: {}, + connectionsBySourceNode: {}, + renameNode: vi.fn(), + }); + + const canvasOperations = useCanvasOperations(); + const workflowDataWithName = { + name: 'Test Workflow Name', + nodes: [], + connections: {}, + }; + + await canvasOperations.importWorkflowData(workflowDataWithName, 'file'); + + expect(workflowsStore.setWorkflowName).toHaveBeenCalledWith({ + newName: 'Test Workflow Name', + setStateDirty: true, + }); + }); }); describe('duplicateNodes', () => { diff --git a/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts b/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts index 8c9cd75fb9..1e8d4473ab 100644 --- a/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts +++ b/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts @@ -2006,6 +2006,10 @@ export function useCanvasOperations() { await importWorkflowTags(workflowData); } + if (workflowData.name) { + workflowsStore.setWorkflowName({ newName: workflowData.name, setStateDirty: true }); + } + return workflowData; } catch (error) { toast.showError(error, i18n.baseText('nodeView.showError.importWorkflowData.title'));