mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-19 11:01:15 +00:00
feat(editor): Don't confirm archiving nonactive workflows (no-changelog) (#15182)
This commit is contained in:
@@ -68,7 +68,6 @@ describe('Workflows', () => {
|
|||||||
for (let i = 0; i < multipleWorkflowsCount + 1; i++) {
|
for (let i = 0; i < multipleWorkflowsCount + 1; i++) {
|
||||||
cy.getByTestId('workflow-card-actions').first().click();
|
cy.getByTestId('workflow-card-actions').first().click();
|
||||||
WorkflowsPage.getters.workflowArchiveButton().click();
|
WorkflowsPage.getters.workflowArchiveButton().click();
|
||||||
cy.get('button').contains('archive').click();
|
|
||||||
successToast().should('be.visible');
|
successToast().should('be.visible');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +157,6 @@ describe('Workflows', () => {
|
|||||||
// Archive -> Unarchive -> Archive -> Delete on the first workflow
|
// Archive -> Unarchive -> Archive -> Delete on the first workflow
|
||||||
cy.getByTestId('workflow-card-actions').first().click();
|
cy.getByTestId('workflow-card-actions').first().click();
|
||||||
WorkflowsPage.getters.workflowArchiveButton().click();
|
WorkflowsPage.getters.workflowArchiveButton().click();
|
||||||
cy.get('button').contains('archive').click();
|
|
||||||
successToast().should('be.visible');
|
successToast().should('be.visible');
|
||||||
|
|
||||||
cy.getByTestId('workflow-card-actions').first().click();
|
cy.getByTestId('workflow-card-actions').first().click();
|
||||||
@@ -167,7 +165,6 @@ describe('Workflows', () => {
|
|||||||
|
|
||||||
cy.getByTestId('workflow-card-actions').first().click();
|
cy.getByTestId('workflow-card-actions').first().click();
|
||||||
WorkflowsPage.getters.workflowArchiveButton().click();
|
WorkflowsPage.getters.workflowArchiveButton().click();
|
||||||
cy.get('button').contains('archive').click();
|
|
||||||
successToast().should('be.visible');
|
successToast().should('be.visible');
|
||||||
|
|
||||||
cy.getByTestId('workflow-card-actions').first().click();
|
cy.getByTestId('workflow-card-actions').first().click();
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ describe('Workflow Actions', () => {
|
|||||||
.should('have.class', 'is-disabled');
|
.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.actions.saveWorkflowOnButtonClick();
|
||||||
WorkflowPage.getters.archivedTag().should('not.exist');
|
WorkflowPage.getters.archivedTag().should('not.exist');
|
||||||
|
|
||||||
@@ -275,7 +275,6 @@ describe('Workflow Actions', () => {
|
|||||||
WorkflowPage.getters.workflowMenu().should('be.visible');
|
WorkflowPage.getters.workflowMenu().should('be.visible');
|
||||||
WorkflowPage.getters.workflowMenu().click();
|
WorkflowPage.getters.workflowMenu().click();
|
||||||
WorkflowPage.getters.workflowMenuItemArchive().click();
|
WorkflowPage.getters.workflowMenuItemArchive().click();
|
||||||
WorkflowPage.actions.acceptConfirmModal();
|
|
||||||
|
|
||||||
successToast().should('exist');
|
successToast().should('exist');
|
||||||
cy.url().should('include', WorkflowPages.url);
|
cy.url().should('include', WorkflowPages.url);
|
||||||
@@ -295,8 +294,11 @@ describe('Workflow Actions', () => {
|
|||||||
cy.url().should('include', WorkflowPages.url);
|
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.saveWorkflowOnButtonClick();
|
||||||
|
WorkflowPage.actions.activateWorkflow();
|
||||||
|
WorkflowPage.getters.isWorkflowActivated();
|
||||||
WorkflowPage.getters.archivedTag().should('not.exist');
|
WorkflowPage.getters.archivedTag().should('not.exist');
|
||||||
|
|
||||||
// Archive the workflow
|
// Archive the workflow
|
||||||
@@ -304,6 +306,35 @@ describe('Workflow Actions', () => {
|
|||||||
WorkflowPage.getters.workflowMenu().click();
|
WorkflowPage.getters.workflowMenu().click();
|
||||||
WorkflowPage.getters.workflowMenuItemArchive().click();
|
WorkflowPage.getters.workflowMenuItemArchive().click();
|
||||||
WorkflowPage.actions.acceptConfirmModal();
|
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');
|
successToast().should('exist');
|
||||||
cy.url().should('include', WorkflowPages.url);
|
cy.url().should('include', WorkflowPages.url);
|
||||||
|
|
||||||
|
|||||||
@@ -298,10 +298,38 @@ describe('WorkflowDetails', () => {
|
|||||||
expect(queryByTestId('workflow-menu-item-unarchive')).not.toBeInTheDocument();
|
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({
|
const { getByTestId } = renderComponent({
|
||||||
props: {
|
props: {
|
||||||
...workflow,
|
...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,
|
readOnly: false,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
scopes: ['workflow:delete'],
|
scopes: ['workflow:delete'],
|
||||||
|
|||||||
@@ -535,6 +535,7 @@ async function onWorkflowMenuSelect(action: WORKFLOW_MENU_ACTIONS): Promise<void
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WORKFLOW_MENU_ACTIONS.ARCHIVE: {
|
case WORKFLOW_MENU_ACTIONS.ARCHIVE: {
|
||||||
|
if (props.active) {
|
||||||
const archiveConfirmed = await message.confirm(
|
const archiveConfirmed = await message.confirm(
|
||||||
locale.baseText('mainSidebar.confirmMessage.workflowArchive.message', {
|
locale.baseText('mainSidebar.confirmMessage.workflowArchive.message', {
|
||||||
interpolate: { workflowName: props.name },
|
interpolate: { workflowName: props.name },
|
||||||
@@ -554,6 +555,7 @@ async function onWorkflowMenuSelect(action: WORKFLOW_MENU_ACTIONS): Promise<void
|
|||||||
if (archiveConfirmed !== MODAL_CONFIRM) {
|
if (archiveConfirmed !== MODAL_CONFIRM) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await workflowsStore.archiveWorkflow(props.id);
|
await workflowsStore.archiveWorkflow(props.id);
|
||||||
|
|||||||
@@ -202,9 +202,46 @@ describe('WorkflowCard', () => {
|
|||||||
expect(actions).toHaveTextContent('Change owner');
|
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({
|
const data = createWorkflow({
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
active: true,
|
||||||
scopes: ['workflow:delete'],
|
scopes: ['workflow:delete'],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -232,7 +269,7 @@ describe('WorkflowCard', () => {
|
|||||||
expect(message.confirm).toHaveBeenCalledTimes(1);
|
expect(message.confirm).toHaveBeenCalledTimes(1);
|
||||||
expect(workflowsStore.archiveWorkflow).toHaveBeenCalledTimes(1);
|
expect(workflowsStore.archiveWorkflow).toHaveBeenCalledTimes(1);
|
||||||
expect(workflowsStore.archiveWorkflow).toHaveBeenCalledWith(data.id);
|
expect(workflowsStore.archiveWorkflow).toHaveBeenCalledWith(data.id);
|
||||||
expect(toast.showError).toHaveBeenCalledTimes(0);
|
expect(toast.showError).not.toHaveBeenCalled();
|
||||||
expect(toast.showMessage).toHaveBeenCalledTimes(1);
|
expect(toast.showMessage).toHaveBeenCalledTimes(1);
|
||||||
expect(emitted()['workflow:archived']).toHaveLength(1);
|
expect(emitted()['workflow:archived']).toHaveLength(1);
|
||||||
});
|
});
|
||||||
@@ -266,7 +303,7 @@ describe('WorkflowCard', () => {
|
|||||||
|
|
||||||
expect(workflowsStore.unarchiveWorkflow).toHaveBeenCalledTimes(1);
|
expect(workflowsStore.unarchiveWorkflow).toHaveBeenCalledTimes(1);
|
||||||
expect(workflowsStore.unarchiveWorkflow).toHaveBeenCalledWith(data.id);
|
expect(workflowsStore.unarchiveWorkflow).toHaveBeenCalledWith(data.id);
|
||||||
expect(toast.showError).toHaveBeenCalledTimes(0);
|
expect(toast.showError).not.toHaveBeenCalled();
|
||||||
expect(toast.showMessage).toHaveBeenCalledTimes(1);
|
expect(toast.showMessage).toHaveBeenCalledTimes(1);
|
||||||
expect(emitted()['workflow:unarchived']).toHaveLength(1);
|
expect(emitted()['workflow:unarchived']).toHaveLength(1);
|
||||||
});
|
});
|
||||||
@@ -301,7 +338,7 @@ describe('WorkflowCard', () => {
|
|||||||
expect(message.confirm).toHaveBeenCalledTimes(1);
|
expect(message.confirm).toHaveBeenCalledTimes(1);
|
||||||
expect(workflowsStore.deleteWorkflow).toHaveBeenCalledTimes(1);
|
expect(workflowsStore.deleteWorkflow).toHaveBeenCalledTimes(1);
|
||||||
expect(workflowsStore.deleteWorkflow).toHaveBeenCalledWith(data.id);
|
expect(workflowsStore.deleteWorkflow).toHaveBeenCalledWith(data.id);
|
||||||
expect(toast.showError).toHaveBeenCalledTimes(0);
|
expect(toast.showError).not.toHaveBeenCalled();
|
||||||
expect(toast.showMessage).toHaveBeenCalledTimes(1);
|
expect(toast.showMessage).toHaveBeenCalledTimes(1);
|
||||||
expect(emitted()['workflow:deleted']).toHaveLength(1);
|
expect(emitted()['workflow:deleted']).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ async function deleteWorkflow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function archiveWorkflow() {
|
async function archiveWorkflow() {
|
||||||
|
if (props.data.active) {
|
||||||
const archiveConfirmed = await message.confirm(
|
const archiveConfirmed = await message.confirm(
|
||||||
locale.baseText('mainSidebar.confirmMessage.workflowArchive.message', {
|
locale.baseText('mainSidebar.confirmMessage.workflowArchive.message', {
|
||||||
interpolate: { workflowName: props.data.name },
|
interpolate: { workflowName: props.data.name },
|
||||||
@@ -326,6 +327,7 @@ async function archiveWorkflow() {
|
|||||||
if (archiveConfirmed !== MODAL_CONFIRM) {
|
if (archiveConfirmed !== MODAL_CONFIRM) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await workflowsStore.archiveWorkflow(props.data.id);
|
await workflowsStore.archiveWorkflow(props.data.id);
|
||||||
|
|||||||
@@ -1025,7 +1025,7 @@
|
|||||||
"mainSidebar.confirmMessage.workflowDelete.cancelButtonText": "",
|
"mainSidebar.confirmMessage.workflowDelete.cancelButtonText": "",
|
||||||
"mainSidebar.confirmMessage.workflowDelete.confirmButtonText": "Yes, delete",
|
"mainSidebar.confirmMessage.workflowDelete.confirmButtonText": "Yes, delete",
|
||||||
"mainSidebar.confirmMessage.workflowDelete.headline": "Delete Workflow?",
|
"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.credentials": "Credentials",
|
||||||
"mainSidebar.variables": "Variables",
|
"mainSidebar.variables": "Variables",
|
||||||
"mainSidebar.help": "Help",
|
"mainSidebar.help": "Help",
|
||||||
|
|||||||
Reference in New Issue
Block a user