diff --git a/cypress/e2e/1-workflows.cy.ts b/cypress/e2e/1-workflows.cy.ts index af6077b7030..b447d1aa96c 100644 --- a/cypress/e2e/1-workflows.cy.ts +++ b/cypress/e2e/1-workflows.cy.ts @@ -68,7 +68,6 @@ describe('Workflows', () => { for (let i = 0; i < multipleWorkflowsCount + 1; i++) { cy.getByTestId('workflow-card-actions').first().click(); WorkflowsPage.getters.workflowArchiveButton().click(); - cy.get('button').contains('archive').click(); successToast().should('be.visible'); } @@ -158,7 +157,6 @@ describe('Workflows', () => { // Archive -> Unarchive -> Archive -> Delete on the first workflow cy.getByTestId('workflow-card-actions').first().click(); WorkflowsPage.getters.workflowArchiveButton().click(); - cy.get('button').contains('archive').click(); successToast().should('be.visible'); cy.getByTestId('workflow-card-actions').first().click(); @@ -167,7 +165,6 @@ describe('Workflows', () => { cy.getByTestId('workflow-card-actions').first().click(); WorkflowsPage.getters.workflowArchiveButton().click(); - cy.get('button').contains('archive').click(); successToast().should('be.visible'); cy.getByTestId('workflow-card-actions').first().click(); diff --git a/cypress/e2e/7-workflow-actions.cy.ts b/cypress/e2e/7-workflow-actions.cy.ts index df1aadc0540..9bd8698a2b1 100644 --- a/cypress/e2e/7-workflow-actions.cy.ts +++ b/cypress/e2e/7-workflow-actions.cy.ts @@ -267,7 +267,7 @@ describe('Workflow Actions', () => { .should('have.class', 'is-disabled'); }); - it('should archive workflow and then delete it', () => { + it('should archive nonactive workflow and then delete it', () => { WorkflowPage.actions.saveWorkflowOnButtonClick(); WorkflowPage.getters.archivedTag().should('not.exist'); @@ -275,7 +275,6 @@ describe('Workflow Actions', () => { WorkflowPage.getters.workflowMenu().should('be.visible'); WorkflowPage.getters.workflowMenu().click(); WorkflowPage.getters.workflowMenuItemArchive().click(); - WorkflowPage.actions.acceptConfirmModal(); successToast().should('exist'); cy.url().should('include', WorkflowPages.url); @@ -295,8 +294,11 @@ describe('Workflow Actions', () => { cy.url().should('include', WorkflowPages.url); }); - it('should archive workflow and then unarchive it', () => { + it('should archive active workflow and then delete it', () => { + WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); WorkflowPage.actions.saveWorkflowOnButtonClick(); + WorkflowPage.actions.activateWorkflow(); + WorkflowPage.getters.isWorkflowActivated(); WorkflowPage.getters.archivedTag().should('not.exist'); // Archive the workflow @@ -304,6 +306,35 @@ describe('Workflow Actions', () => { WorkflowPage.getters.workflowMenu().click(); WorkflowPage.getters.workflowMenuItemArchive().click(); WorkflowPage.actions.acceptConfirmModal(); + + successToast().should('exist'); + cy.url().should('include', WorkflowPages.url); + + // Return back to the workflow + cy.go('back'); + + WorkflowPage.getters.archivedTag().should('be.visible'); + WorkflowPage.getters.nodeCreatorPlusButton().should('not.exist'); + WorkflowPage.getters.isWorkflowDeactivated(); + + // Delete the workflow + WorkflowPage.getters.workflowMenu().should('be.visible'); + WorkflowPage.getters.workflowMenu().click(); + WorkflowPage.getters.workflowMenuItemDelete().click(); + WorkflowPage.actions.acceptConfirmModal(); + successToast().should('exist'); + cy.url().should('include', WorkflowPages.url); + }); + + it('should archive nonactive workflow and then unarchive it', () => { + WorkflowPage.actions.saveWorkflowOnButtonClick(); + WorkflowPage.getters.archivedTag().should('not.exist'); + + // Archive the workflow + WorkflowPage.getters.workflowMenu().should('be.visible'); + WorkflowPage.getters.workflowMenu().click(); + WorkflowPage.getters.workflowMenuItemArchive().click(); + successToast().should('exist'); cy.url().should('include', WorkflowPages.url); diff --git a/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.test.ts b/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.test.ts index fc7563dfa20..f31edb561fb 100644 --- a/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.test.ts +++ b/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.test.ts @@ -298,10 +298,38 @@ describe('WorkflowDetails', () => { expect(queryByTestId('workflow-menu-item-unarchive')).not.toBeInTheDocument(); }); - it("should call onWorkflowMenuSelect on 'Archive' option click", async () => { + it("should call onWorkflowMenuSelect on 'Archive' option click on nonactive workflow", async () => { const { getByTestId } = renderComponent({ props: { ...workflow, + active: false, + readOnly: false, + isArchived: false, + scopes: ['workflow:delete'], + }, + }); + + workflowsStore.archiveWorkflow.mockResolvedValue(undefined); + + await userEvent.click(getByTestId('workflow-menu')); + await userEvent.click(getByTestId('workflow-menu-item-archive')); + + expect(message.confirm).toHaveBeenCalledTimes(0); + expect(toast.showError).toHaveBeenCalledTimes(0); + expect(toast.showMessage).toHaveBeenCalledTimes(1); + expect(workflowsStore.archiveWorkflow).toHaveBeenCalledTimes(1); + expect(workflowsStore.archiveWorkflow).toHaveBeenCalledWith(workflow.id); + expect(router.push).toHaveBeenCalledTimes(1); + expect(router.push).toHaveBeenCalledWith({ + name: VIEWS.WORKFLOWS, + }); + }); + + it("should confirm onWorkflowMenuSelect on 'Archive' option click on active workflow", async () => { + const { getByTestId } = renderComponent({ + props: { + ...workflow, + active: true, readOnly: false, isArchived: false, scopes: ['workflow:delete'], diff --git a/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.vue b/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.vue index 1eff2ff642d..05c37df349b 100644 --- a/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.vue +++ b/packages/frontend/editor-ui/src/components/MainHeader/WorkflowDetails.vue @@ -535,24 +535,26 @@ async function onWorkflowMenuSelect(action: WORKFLOW_MENU_ACTIONS): Promise { expect(actions).toHaveTextContent('Change owner'); }); - it("should have 'Archive' action on non archived workflows", async () => { + it("should have 'Archive' action on non archived nonactive workflows", async () => { + const data = createWorkflow({ + active: false, + isArchived: false, + scopes: ['workflow:delete'], + }); + + const { getByTestId, emitted } = renderComponent({ + props: { data }, + }); + const cardActions = getByTestId('workflow-card-actions'); + expect(cardActions).toBeInTheDocument(); + + const cardActionsOpener = within(cardActions).getByRole('button'); + expect(cardActionsOpener).toBeInTheDocument(); + + const controllingId = cardActionsOpener.getAttribute('aria-controls'); + await userEvent.click(cardActions); + const actions = document.querySelector(`#${controllingId}`); + if (!actions) { + throw new Error('Actions menu not found'); + } + expect(actions).toHaveTextContent('Archive'); + expect(actions).not.toHaveTextContent('Unarchive'); + expect(actions).not.toHaveTextContent('Delete'); + + await userEvent.click(getByTestId('action-archive')); + + expect(message.confirm).not.toHaveBeenCalled(); + expect(workflowsStore.archiveWorkflow).toHaveBeenCalledTimes(1); + expect(workflowsStore.archiveWorkflow).toHaveBeenCalledWith(data.id); + expect(toast.showError).not.toHaveBeenCalled(); + expect(toast.showMessage).toHaveBeenCalledTimes(1); + expect(emitted()['workflow:archived']).toHaveLength(1); + }); + + it("should confirm 'Archive' action on active workflows", async () => { const data = createWorkflow({ isArchived: false, + active: true, scopes: ['workflow:delete'], }); @@ -232,7 +269,7 @@ describe('WorkflowCard', () => { expect(message.confirm).toHaveBeenCalledTimes(1); expect(workflowsStore.archiveWorkflow).toHaveBeenCalledTimes(1); expect(workflowsStore.archiveWorkflow).toHaveBeenCalledWith(data.id); - expect(toast.showError).toHaveBeenCalledTimes(0); + expect(toast.showError).not.toHaveBeenCalled(); expect(toast.showMessage).toHaveBeenCalledTimes(1); expect(emitted()['workflow:archived']).toHaveLength(1); }); @@ -266,7 +303,7 @@ describe('WorkflowCard', () => { expect(workflowsStore.unarchiveWorkflow).toHaveBeenCalledTimes(1); expect(workflowsStore.unarchiveWorkflow).toHaveBeenCalledWith(data.id); - expect(toast.showError).toHaveBeenCalledTimes(0); + expect(toast.showError).not.toHaveBeenCalled(); expect(toast.showMessage).toHaveBeenCalledTimes(1); expect(emitted()['workflow:unarchived']).toHaveLength(1); }); @@ -301,7 +338,7 @@ describe('WorkflowCard', () => { expect(message.confirm).toHaveBeenCalledTimes(1); expect(workflowsStore.deleteWorkflow).toHaveBeenCalledTimes(1); expect(workflowsStore.deleteWorkflow).toHaveBeenCalledWith(data.id); - expect(toast.showError).toHaveBeenCalledTimes(0); + expect(toast.showError).not.toHaveBeenCalled(); expect(toast.showMessage).toHaveBeenCalledTimes(1); expect(emitted()['workflow:deleted']).toHaveLength(1); }); diff --git a/packages/frontend/editor-ui/src/components/WorkflowCard.vue b/packages/frontend/editor-ui/src/components/WorkflowCard.vue index f8723584188..91d6b33d057 100644 --- a/packages/frontend/editor-ui/src/components/WorkflowCard.vue +++ b/packages/frontend/editor-ui/src/components/WorkflowCard.vue @@ -307,24 +307,26 @@ async function deleteWorkflow() { } async function archiveWorkflow() { - const archiveConfirmed = await message.confirm( - locale.baseText('mainSidebar.confirmMessage.workflowArchive.message', { - interpolate: { workflowName: props.data.name }, - }), - locale.baseText('mainSidebar.confirmMessage.workflowArchive.headline'), - { - type: 'warning', - confirmButtonText: locale.baseText( - 'mainSidebar.confirmMessage.workflowArchive.confirmButtonText', - ), - cancelButtonText: locale.baseText( - 'mainSidebar.confirmMessage.workflowArchive.cancelButtonText', - ), - }, - ); + if (props.data.active) { + const archiveConfirmed = await message.confirm( + locale.baseText('mainSidebar.confirmMessage.workflowArchive.message', { + interpolate: { workflowName: props.data.name }, + }), + locale.baseText('mainSidebar.confirmMessage.workflowArchive.headline'), + { + type: 'warning', + confirmButtonText: locale.baseText( + 'mainSidebar.confirmMessage.workflowArchive.confirmButtonText', + ), + cancelButtonText: locale.baseText( + 'mainSidebar.confirmMessage.workflowArchive.cancelButtonText', + ), + }, + ); - if (archiveConfirmed !== MODAL_CONFIRM) { - return; + if (archiveConfirmed !== MODAL_CONFIRM) { + return; + } } try { diff --git a/packages/frontend/editor-ui/src/plugins/i18n/locales/en.json b/packages/frontend/editor-ui/src/plugins/i18n/locales/en.json index 38b759e0f4e..1e83f13581c 100644 --- a/packages/frontend/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/frontend/editor-ui/src/plugins/i18n/locales/en.json @@ -1025,7 +1025,7 @@ "mainSidebar.confirmMessage.workflowDelete.cancelButtonText": "", "mainSidebar.confirmMessage.workflowDelete.confirmButtonText": "Yes, delete", "mainSidebar.confirmMessage.workflowDelete.headline": "Delete Workflow?", - "mainSidebar.confirmMessage.workflowDelete.message": "Are you sure that you want to delete '{workflowName}'?", + "mainSidebar.confirmMessage.workflowDelete.message": "Are you sure that you want to delete '{workflowName}' permanently?", "mainSidebar.credentials": "Credentials", "mainSidebar.variables": "Variables", "mainSidebar.help": "Help",