mirror of
https://github.com/n8n-io/n8n.git
synced 2024-10-06 09:37:36 +03:00
fix(editor): Fix opening executions tab from a new, unsaved workflow (#10652)
This commit is contained in:
parent
746e7b89f7
commit
cd0891e4f1
@ -9,223 +9,252 @@ const executionsTab = new WorkflowExecutionsTab();
|
|||||||
const executionsRefreshInterval = 4000;
|
const executionsRefreshInterval = 4000;
|
||||||
|
|
||||||
// Test suite for executions tab
|
// Test suite for executions tab
|
||||||
describe('Current Workflow Executions', () => {
|
describe('Workflow Executions', () => {
|
||||||
beforeEach(() => {
|
describe('when workflow is saved', () => {
|
||||||
workflowPage.actions.visit();
|
beforeEach(() => {
|
||||||
cy.createFixtureWorkflow('Test_workflow_4_executions_view.json', 'My test workflow');
|
workflowPage.actions.visit();
|
||||||
});
|
cy.createFixtureWorkflow('Test_workflow_4_executions_view.json', 'My test workflow');
|
||||||
|
|
||||||
it('should render executions tab correctly', () => {
|
|
||||||
createMockExecutions();
|
|
||||||
cy.intercept('GET', '/rest/executions?filter=*').as('getExecutions');
|
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
|
|
||||||
cy.wait(['@getExecutions']);
|
|
||||||
|
|
||||||
executionsTab.getters.executionsList().scrollTo(0, 500).wait(0);
|
|
||||||
|
|
||||||
executionsTab.getters.executionListItems().should('have.length', 11);
|
|
||||||
executionsTab.getters.successfulExecutionListItems().should('have.length', 9);
|
|
||||||
executionsTab.getters.failedExecutionListItems().should('have.length', 2);
|
|
||||||
executionsTab.getters
|
|
||||||
.executionListItems()
|
|
||||||
.first()
|
|
||||||
.invoke('attr', 'class')
|
|
||||||
.should('match', /_active_/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not redirect back to execution tab when request is not done before leaving the page', () => {
|
|
||||||
cy.intercept('GET', '/rest/executions?filter=*');
|
|
||||||
cy.intercept('GET', '/rest/executions/active?filter=*');
|
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
cy.wait(executionsRefreshInterval);
|
|
||||||
cy.url().should('not.include', '/executions');
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
cy.wait(executionsRefreshInterval);
|
|
||||||
cy.url().should('not.include', '/executions');
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
cy.wait(1000);
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
cy.wait(executionsRefreshInterval);
|
|
||||||
cy.url().should('not.include', '/executions');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not redirect back to execution tab when slow request is not done before leaving the page', () => {
|
|
||||||
const throttleResponse: RouteHandler = async (req) => {
|
|
||||||
return await new Promise((resolve) => {
|
|
||||||
setTimeout(() => resolve(req.continue()), 2000);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.intercept('GET', '/rest/executions?filter=*', throttleResponse);
|
|
||||||
cy.intercept('GET', '/rest/executions/active?filter=*', throttleResponse);
|
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
cy.wait(executionsRefreshInterval);
|
|
||||||
cy.url().should('not.include', '/executions');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should error toast when server error message returned without stack trace', () => {
|
|
||||||
executionsTab.actions.createManualExecutions(1);
|
|
||||||
const message = 'Workflow did not finish, possible out-of-memory issue';
|
|
||||||
cy.intercept('GET', '/rest/executions/*', {
|
|
||||||
statusCode: 200,
|
|
||||||
body: executionOutOfMemoryServerResponse,
|
|
||||||
}).as('getExecution');
|
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
cy.wait(['@getExecution']);
|
|
||||||
|
|
||||||
executionsTab.getters
|
|
||||||
.workflowExecutionPreviewIframe()
|
|
||||||
.should('be.visible')
|
|
||||||
.its('0.contentDocument.body') // Access the body of the iframe document
|
|
||||||
.should('not.be.empty') // Ensure the body is not empty
|
|
||||||
|
|
||||||
.then(cy.wrap)
|
|
||||||
.find('.el-notification:has(.el-notification--error)')
|
|
||||||
.should('be.visible')
|
|
||||||
.filter(`:contains("${message}")`)
|
|
||||||
.should('be.visible');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show workflow data in executions tab after hard reload and modify name and tags', () => {
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
checkMainHeaderELements();
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 2);
|
|
||||||
|
|
||||||
workflowPage.getters.workflowTags().click();
|
|
||||||
getVisibleSelect().find('li:contains("Manage tags")').click();
|
|
||||||
cy.get('button:contains("Add new")').click();
|
|
||||||
cy.getByTestId('tags-table').find('input').type('nutag').type('{enter}');
|
|
||||||
cy.get('button:contains("Done")').click();
|
|
||||||
|
|
||||||
cy.reload();
|
|
||||||
checkMainHeaderELements();
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.workflowTags().click();
|
|
||||||
workflowPage.getters.tagsInDropdown().first().should('have.text', 'nutag').click();
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 3);
|
|
||||||
|
|
||||||
let newWorkflowName = 'Renamed workflow';
|
|
||||||
workflowPage.actions.renameWorkflow(newWorkflowName);
|
|
||||||
workflowPage.getters.isWorkflowSaved();
|
|
||||||
workflowPage.getters
|
|
||||||
.workflowNameInputContainer()
|
|
||||||
.invoke('attr', 'title')
|
|
||||||
.should('eq', newWorkflowName);
|
|
||||||
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
checkMainHeaderELements();
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 3);
|
|
||||||
workflowPage.getters
|
|
||||||
.workflowNameInputContainer()
|
|
||||||
.invoke('attr', 'title')
|
|
||||||
.should('eq', newWorkflowName);
|
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
checkMainHeaderELements();
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 3);
|
|
||||||
workflowPage.getters
|
|
||||||
.workflowNameInputContainer()
|
|
||||||
.invoke('attr', 'title')
|
|
||||||
.should('eq', newWorkflowName);
|
|
||||||
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
checkMainHeaderELements();
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 3);
|
|
||||||
workflowPage.getters
|
|
||||||
.workflowNameInputContainer()
|
|
||||||
.invoke('attr', 'title')
|
|
||||||
.should('eq', newWorkflowName);
|
|
||||||
|
|
||||||
newWorkflowName = 'New workflow';
|
|
||||||
workflowPage.actions.renameWorkflow(newWorkflowName);
|
|
||||||
workflowPage.getters.isWorkflowSaved();
|
|
||||||
workflowPage.getters
|
|
||||||
.workflowNameInputContainer()
|
|
||||||
.invoke('attr', 'title')
|
|
||||||
.should('eq', newWorkflowName);
|
|
||||||
workflowPage.getters.workflowTags().click();
|
|
||||||
workflowPage.getters.tagsDropdown().find('.el-tag__close').first().click();
|
|
||||||
cy.get('body').click(0, 0);
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 2);
|
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
checkMainHeaderELements();
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 2);
|
|
||||||
workflowPage.getters
|
|
||||||
.workflowNameInputContainer()
|
|
||||||
.invoke('attr', 'title')
|
|
||||||
.should('eq', newWorkflowName);
|
|
||||||
|
|
||||||
executionsTab.actions.switchToEditorTab();
|
|
||||||
checkMainHeaderELements();
|
|
||||||
workflowPage.getters.saveButton().find('button').should('not.exist');
|
|
||||||
workflowPage.getters.tagPills().should('have.length', 2);
|
|
||||||
workflowPage.getters
|
|
||||||
.workflowNameInputContainer()
|
|
||||||
.invoke('attr', 'title')
|
|
||||||
.should('eq', newWorkflowName);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should load items and auto scroll after filter change', () => {
|
|
||||||
createMockExecutions();
|
|
||||||
createMockExecutions();
|
|
||||||
cy.intercept('GET', '/rest/executions?filter=*').as('getExecutions');
|
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
|
||||||
|
|
||||||
cy.wait(['@getExecutions']);
|
|
||||||
|
|
||||||
executionsTab.getters.executionsList().scrollTo(0, 500).wait(0);
|
|
||||||
|
|
||||||
executionsTab.getters.executionListItems().eq(10).click();
|
|
||||||
|
|
||||||
cy.getByTestId('executions-filter-button').click();
|
|
||||||
cy.getByTestId('executions-filter-status-select').should('be.visible').click();
|
|
||||||
getVisibleSelect().find('li:contains("Error")').click();
|
|
||||||
|
|
||||||
executionsTab.getters.executionListItems().should('have.length', 5);
|
|
||||||
executionsTab.getters.successfulExecutionListItems().should('have.length', 1);
|
|
||||||
executionsTab.getters.failedExecutionListItems().should('have.length', 4);
|
|
||||||
|
|
||||||
cy.getByTestId('executions-filter-button').click();
|
|
||||||
cy.getByTestId('executions-filter-status-select').should('be.visible').click();
|
|
||||||
getVisibleSelect().find('li:contains("Success")').click();
|
|
||||||
|
|
||||||
// check if the list is scrolled
|
|
||||||
executionsTab.getters.executionListItems().eq(10).should('be.visible');
|
|
||||||
executionsTab.getters.executionsList().then(($el) => {
|
|
||||||
const { scrollTop, scrollHeight, clientHeight } = $el[0];
|
|
||||||
expect(scrollTop).to.be.greaterThan(0);
|
|
||||||
expect(scrollTop + clientHeight).to.be.lessThan(scrollHeight);
|
|
||||||
|
|
||||||
// scroll to the bottom
|
|
||||||
$el[0].scrollTo(0, scrollHeight);
|
|
||||||
executionsTab.getters.executionListItems().should('have.length', 18);
|
|
||||||
executionsTab.getters.successfulExecutionListItems().should('have.length', 18);
|
|
||||||
executionsTab.getters.failedExecutionListItems().should('have.length', 0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.getByTestId('executions-filter-button').click();
|
it('should render executions tab correctly', () => {
|
||||||
cy.getByTestId('executions-filter-reset-button').should('be.visible').click();
|
createMockExecutions();
|
||||||
executionsTab.getters.executionListItems().eq(11).should('be.visible');
|
cy.intercept('GET', '/rest/executions?filter=*').as('getExecutions');
|
||||||
|
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
|
||||||
|
cy.wait(['@getExecutions']);
|
||||||
|
|
||||||
|
executionsTab.getters.executionsList().scrollTo(0, 500).wait(0);
|
||||||
|
|
||||||
|
executionsTab.getters.executionListItems().should('have.length', 11);
|
||||||
|
executionsTab.getters.successfulExecutionListItems().should('have.length', 9);
|
||||||
|
executionsTab.getters.failedExecutionListItems().should('have.length', 2);
|
||||||
|
executionsTab.getters
|
||||||
|
.executionListItems()
|
||||||
|
.first()
|
||||||
|
.invoke('attr', 'class')
|
||||||
|
.should('match', /_active_/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not redirect back to execution tab when request is not done before leaving the page', () => {
|
||||||
|
cy.intercept('GET', '/rest/executions?filter=*');
|
||||||
|
cy.intercept('GET', '/rest/executions/active?filter=*');
|
||||||
|
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
cy.wait(executionsRefreshInterval);
|
||||||
|
cy.url().should('not.include', '/executions');
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
cy.wait(executionsRefreshInterval);
|
||||||
|
cy.url().should('not.include', '/executions');
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
cy.wait(1000);
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
cy.wait(executionsRefreshInterval);
|
||||||
|
cy.url().should('not.include', '/executions');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not redirect back to execution tab when slow request is not done before leaving the page', () => {
|
||||||
|
const throttleResponse: RouteHandler = async (req) => {
|
||||||
|
return await new Promise((resolve) => {
|
||||||
|
setTimeout(() => resolve(req.continue()), 2000);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
cy.intercept('GET', '/rest/executions?filter=*', throttleResponse);
|
||||||
|
cy.intercept('GET', '/rest/executions/active?filter=*', throttleResponse);
|
||||||
|
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
cy.wait(executionsRefreshInterval);
|
||||||
|
cy.url().should('not.include', '/executions');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error toast when server error message returned without stack trace', () => {
|
||||||
|
executionsTab.actions.createManualExecutions(1);
|
||||||
|
const message = 'Workflow did not finish, possible out-of-memory issue';
|
||||||
|
cy.intercept('GET', '/rest/executions/*', {
|
||||||
|
statusCode: 200,
|
||||||
|
body: executionOutOfMemoryServerResponse,
|
||||||
|
}).as('getExecution');
|
||||||
|
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
cy.wait(['@getExecution']);
|
||||||
|
|
||||||
|
executionsTab.getters
|
||||||
|
.workflowExecutionPreviewIframe()
|
||||||
|
.should('be.visible')
|
||||||
|
.its('0.contentDocument.body') // Access the body of the iframe document
|
||||||
|
.should('not.be.empty') // Ensure the body is not empty
|
||||||
|
|
||||||
|
.then(cy.wrap)
|
||||||
|
.find('.el-notification:has(.el-notification--error)')
|
||||||
|
.should('be.visible')
|
||||||
|
.filter(`:contains("${message}")`)
|
||||||
|
.should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show workflow data in executions tab after hard reload and modify name and tags', () => {
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
checkMainHeaderELements();
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 2);
|
||||||
|
|
||||||
|
workflowPage.getters.workflowTags().click();
|
||||||
|
getVisibleSelect().find('li:contains("Manage tags")').click();
|
||||||
|
cy.get('button:contains("Add new")').click();
|
||||||
|
cy.getByTestId('tags-table').find('input').type('nutag').type('{enter}');
|
||||||
|
cy.get('button:contains("Done")').click();
|
||||||
|
|
||||||
|
cy.reload();
|
||||||
|
checkMainHeaderELements();
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.workflowTags().click();
|
||||||
|
workflowPage.getters.tagsInDropdown().first().should('have.text', 'nutag').click();
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 3);
|
||||||
|
|
||||||
|
let newWorkflowName = 'Renamed workflow';
|
||||||
|
workflowPage.actions.renameWorkflow(newWorkflowName);
|
||||||
|
workflowPage.getters.isWorkflowSaved();
|
||||||
|
workflowPage.getters
|
||||||
|
.workflowNameInputContainer()
|
||||||
|
.invoke('attr', 'title')
|
||||||
|
.should('eq', newWorkflowName);
|
||||||
|
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
checkMainHeaderELements();
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 3);
|
||||||
|
workflowPage.getters
|
||||||
|
.workflowNameInputContainer()
|
||||||
|
.invoke('attr', 'title')
|
||||||
|
.should('eq', newWorkflowName);
|
||||||
|
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
checkMainHeaderELements();
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 3);
|
||||||
|
workflowPage.getters
|
||||||
|
.workflowNameInputContainer()
|
||||||
|
.invoke('attr', 'title')
|
||||||
|
.should('eq', newWorkflowName);
|
||||||
|
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
checkMainHeaderELements();
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 3);
|
||||||
|
workflowPage.getters
|
||||||
|
.workflowNameInputContainer()
|
||||||
|
.invoke('attr', 'title')
|
||||||
|
.should('eq', newWorkflowName);
|
||||||
|
|
||||||
|
newWorkflowName = 'New workflow';
|
||||||
|
workflowPage.actions.renameWorkflow(newWorkflowName);
|
||||||
|
workflowPage.getters.isWorkflowSaved();
|
||||||
|
workflowPage.getters
|
||||||
|
.workflowNameInputContainer()
|
||||||
|
.invoke('attr', 'title')
|
||||||
|
.should('eq', newWorkflowName);
|
||||||
|
workflowPage.getters.workflowTags().click();
|
||||||
|
workflowPage.getters.tagsDropdown().find('.el-tag__close').first().click();
|
||||||
|
cy.get('body').click(0, 0);
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 2);
|
||||||
|
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
checkMainHeaderELements();
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 2);
|
||||||
|
workflowPage.getters
|
||||||
|
.workflowNameInputContainer()
|
||||||
|
.invoke('attr', 'title')
|
||||||
|
.should('eq', newWorkflowName);
|
||||||
|
|
||||||
|
executionsTab.actions.switchToEditorTab();
|
||||||
|
checkMainHeaderELements();
|
||||||
|
workflowPage.getters.saveButton().find('button').should('not.exist');
|
||||||
|
workflowPage.getters.tagPills().should('have.length', 2);
|
||||||
|
workflowPage.getters
|
||||||
|
.workflowNameInputContainer()
|
||||||
|
.invoke('attr', 'title')
|
||||||
|
.should('eq', newWorkflowName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load items and auto scroll after filter change', () => {
|
||||||
|
createMockExecutions();
|
||||||
|
createMockExecutions();
|
||||||
|
cy.intercept('GET', '/rest/executions?filter=*').as('getExecutions');
|
||||||
|
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
|
||||||
|
cy.wait(['@getExecutions']);
|
||||||
|
|
||||||
|
executionsTab.getters.executionsList().scrollTo(0, 500).wait(0);
|
||||||
|
|
||||||
|
executionsTab.getters.executionListItems().eq(10).click();
|
||||||
|
|
||||||
|
cy.getByTestId('executions-filter-button').click();
|
||||||
|
cy.getByTestId('executions-filter-status-select').should('be.visible').click();
|
||||||
|
getVisibleSelect().find('li:contains("Error")').click();
|
||||||
|
|
||||||
|
executionsTab.getters.executionListItems().should('have.length', 5);
|
||||||
|
executionsTab.getters.successfulExecutionListItems().should('have.length', 1);
|
||||||
|
executionsTab.getters.failedExecutionListItems().should('have.length', 4);
|
||||||
|
|
||||||
|
cy.getByTestId('executions-filter-button').click();
|
||||||
|
cy.getByTestId('executions-filter-status-select').should('be.visible').click();
|
||||||
|
getVisibleSelect().find('li:contains("Success")').click();
|
||||||
|
|
||||||
|
// check if the list is scrolled
|
||||||
|
executionsTab.getters.executionListItems().eq(10).should('be.visible');
|
||||||
|
executionsTab.getters.executionsList().then(($el) => {
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = $el[0];
|
||||||
|
expect(scrollTop).to.be.greaterThan(0);
|
||||||
|
expect(scrollTop + clientHeight).to.be.lessThan(scrollHeight);
|
||||||
|
|
||||||
|
// scroll to the bottom
|
||||||
|
$el[0].scrollTo(0, scrollHeight);
|
||||||
|
executionsTab.getters.executionListItems().should('have.length', 18);
|
||||||
|
executionsTab.getters.successfulExecutionListItems().should('have.length', 18);
|
||||||
|
executionsTab.getters.failedExecutionListItems().should('have.length', 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.getByTestId('executions-filter-button').click();
|
||||||
|
cy.getByTestId('executions-filter-reset-button').should('be.visible').click();
|
||||||
|
executionsTab.getters.executionListItems().eq(11).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when new workflow is not saved', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
workflowPage.actions.visit();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open executions tab', () => {
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
executionsTab.getters.executionsSidebar().should('be.visible');
|
||||||
|
executionsTab.getters.executionsEmptyList().should('be.visible');
|
||||||
|
cy.getByTestId('workflow-execution-no-trigger-content').should('be.visible');
|
||||||
|
cy.get('button:contains("Add first step")').should('be.visible').click();
|
||||||
|
|
||||||
|
cy.getByTestId('node-creator-item-name')
|
||||||
|
.should('be.visible')
|
||||||
|
.filter(':contains("Trigger")')
|
||||||
|
.click();
|
||||||
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
executionsTab.getters.executionsSidebar().should('be.visible');
|
||||||
|
executionsTab.getters.executionsEmptyList().should('be.visible');
|
||||||
|
cy.getByTestId('workflow-execution-no-content').should('be.visible');
|
||||||
|
|
||||||
|
workflowPage.getters.saveButton().find('button').should('be.enabled').click();
|
||||||
|
workflowPage.getters.isWorkflowSaved();
|
||||||
|
workflowPage.getters.nodeViewRoot().should('be.visible');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ export class WorkflowExecutionsTab extends BasePage {
|
|||||||
getters = {
|
getters = {
|
||||||
executionsTabButton: () => cy.getByTestId('radio-button-executions'),
|
executionsTabButton: () => cy.getByTestId('radio-button-executions'),
|
||||||
executionsSidebar: () => cy.getByTestId('executions-sidebar'),
|
executionsSidebar: () => cy.getByTestId('executions-sidebar'),
|
||||||
|
executionsEmptyList: () => cy.getByTestId('execution-list-empty'),
|
||||||
autoRefreshCheckBox: () => cy.getByTestId('auto-refresh-checkbox'),
|
autoRefreshCheckBox: () => cy.getByTestId('auto-refresh-checkbox'),
|
||||||
executionsList: () => cy.getByTestId('current-executions-list'),
|
executionsList: () => cy.getByTestId('current-executions-list'),
|
||||||
executionListItems: () => this.getters.executionsList().find('div.execution-card'),
|
executionListItems: () => this.getters.executionsList().find('div.execution-card'),
|
||||||
|
@ -36,7 +36,7 @@ function getWorkflowRoute(): { name: string; params: {} } {
|
|||||||
<template>
|
<template>
|
||||||
<div :class="['workflow-executions-container', $style.container]">
|
<div :class="['workflow-executions-container', $style.container]">
|
||||||
<div v-if="executionCount === 0" :class="[$style.messageContainer, $style.noExecutionsMessage]">
|
<div v-if="executionCount === 0" :class="[$style.messageContainer, $style.noExecutionsMessage]">
|
||||||
<div v-if="!containsTrigger">
|
<div v-if="!containsTrigger" data-test-id="workflow-execution-no-trigger-content">
|
||||||
<N8nHeading tag="h2" size="xlarge" color="text-dark" class="mb-2xs">
|
<N8nHeading tag="h2" size="xlarge" color="text-dark" class="mb-2xs">
|
||||||
{{ locale.baseText('executionsLandingPage.emptyState.noTrigger.heading') }}
|
{{ locale.baseText('executionsLandingPage.emptyState.noTrigger.heading') }}
|
||||||
</N8nHeading>
|
</N8nHeading>
|
||||||
@ -47,7 +47,7 @@ function getWorkflowRoute(): { name: string; params: {} } {
|
|||||||
{{ locale.baseText('executionsLandingPage.emptyState.noTrigger.buttonText') }}
|
{{ locale.baseText('executionsLandingPage.emptyState.noTrigger.buttonText') }}
|
||||||
</N8nButton>
|
</N8nButton>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else data-test-id="workflow-execution-no-content">
|
||||||
<N8nHeading tag="h2" size="xlarge" color="text-dark" class="mb-2xs">
|
<N8nHeading tag="h2" size="xlarge" color="text-dark" class="mb-2xs">
|
||||||
{{ locale.baseText('executionsLandingPage.emptyState.heading') }}
|
{{ locale.baseText('executionsLandingPage.emptyState.heading') }}
|
||||||
</N8nHeading>
|
</N8nHeading>
|
||||||
|
@ -500,8 +500,8 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
|
|||||||
executingNode.value = executingNode.value.filter((name) => name !== nodeName);
|
executingNode.value = executingNode.value.filter((name) => name !== nodeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWorkflowId(id: string) {
|
function setWorkflowId(id?: string) {
|
||||||
workflow.value.id = id === 'new' ? PLACEHOLDER_EMPTY_WORKFLOW_ID : id;
|
workflow.value.id = !id || id === 'new' ? PLACEHOLDER_EMPTY_WORKFLOW_ID : id;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUsedCredentials(data: IUsedCredential[]) {
|
function setUsedCredentials(data: IUsedCredential[]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user