mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
ci: Refactor e2e tests to be less flaky (no-changelog) (#9695)
This commit is contained in:
committed by
GitHub
parent
bc35e8c33d
commit
3d0393c739
@@ -122,8 +122,7 @@ describe('Undo/Redo', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
cy.get('body').type('{esc}');
|
||||
cy.get('body').type('{esc}');
|
||||
WorkflowPage.actions.selectAll();
|
||||
cy.get('body').type('{backspace}');
|
||||
WorkflowPage.actions.hitDeleteAllNodes();
|
||||
WorkflowPage.getters.canvasNodes().should('have.have.length', 0);
|
||||
WorkflowPage.actions.hitUndo();
|
||||
WorkflowPage.getters.canvasNodes().should('have.have.length', 2);
|
||||
@@ -208,7 +207,7 @@ describe('Undo/Redo', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
cy.get('body').type('{esc}');
|
||||
cy.get('body').type('{esc}');
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 2);
|
||||
WorkflowPage.actions.hitUndo();
|
||||
|
||||
@@ -199,7 +199,7 @@ describe('Canvas Actions', () => {
|
||||
it('should copy selected nodes', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
|
||||
WorkflowPage.actions.hitCopy();
|
||||
successToast().should('contain', 'Copied!');
|
||||
@@ -211,7 +211,7 @@ describe('Canvas Actions', () => {
|
||||
it('should select/deselect all nodes', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.getters.selectedNodes().should('have.length', 2);
|
||||
WorkflowPage.actions.deselectAll();
|
||||
WorkflowPage.getters.selectedNodes().should('have.length', 0);
|
||||
|
||||
@@ -164,8 +164,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
cy.wait(500);
|
||||
WorkflowPage.actions.selectAll();
|
||||
cy.get('body').type('{backspace}');
|
||||
WorkflowPage.actions.hitDeleteAllNodes();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 0);
|
||||
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
@@ -181,8 +180,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
cy.wait(500);
|
||||
WorkflowPage.actions.selectAll();
|
||||
cy.get('body').type('{backspace}');
|
||||
WorkflowPage.actions.hitDeleteAllNodes();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 0);
|
||||
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
@@ -315,7 +313,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
||||
cy.get('body').type('{esc}');
|
||||
|
||||
// Keyboard shortcut
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 2);
|
||||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
@@ -324,12 +322,12 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
||||
WorkflowPage.getters.canvasNodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 1);
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 2);
|
||||
|
||||
// Context menu
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('toggle_activation');
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 0);
|
||||
@@ -341,7 +339,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('toggle_activation');
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 1);
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('toggle_activation');
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 2);
|
||||
@@ -383,8 +381,8 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 3);
|
||||
WorkflowPage.getters.nodeConnections().should('have.length', 1);
|
||||
|
||||
WorkflowPage.actions.selectAll();
|
||||
WorkflowPage.actions.hitDuplicateNodeShortcut();
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.hitDuplicateNode();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 5);
|
||||
});
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
|
||||
let workflowW2Url = '';
|
||||
it('should create C1, W1, W2, share W1 with U3, as U2', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.emptyListCreateCredentialButton().click();
|
||||
@@ -67,7 +67,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
it('should create C2, share C2 with U1 and U2, as U3', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[1]);
|
||||
cy.signinAsMember(1);
|
||||
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.emptyListCreateCredentialButton().click();
|
||||
@@ -83,7 +83,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
it('should open W1, add node using C2 as U3', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[1]);
|
||||
cy.signinAsMember(1);
|
||||
|
||||
cy.visit(workflowsPage.url);
|
||||
workflowsPage.getters.workflowCards().should('have.length', 1);
|
||||
@@ -99,7 +99,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
it('should open W1, add node using C2 as U2', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
|
||||
cy.visit(workflowsPage.url);
|
||||
workflowsPage.getters.workflowCards().should('have.length', 2);
|
||||
@@ -119,7 +119,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
it('should not have access to W2, as U3', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[1]);
|
||||
cy.signinAsMember(1);
|
||||
|
||||
cy.visit(workflowW2Url);
|
||||
cy.waitForLoad();
|
||||
@@ -128,7 +128,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
it('should have access to W1, W2, as U1', () => {
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
cy.signinAsOwner();
|
||||
|
||||
cy.visit(workflowsPage.url);
|
||||
workflowsPage.getters.workflowCards().should('have.length', 2);
|
||||
@@ -144,7 +144,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
it('should automatically test C2 when opened by U2 sharee', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.credentialCard('Credential C2').click();
|
||||
@@ -152,7 +152,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
it('should work for admin role on credentials created by others (also can share it with themselves)', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.createCredentialButton().click();
|
||||
@@ -164,7 +164,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
credentialsModal.actions.close();
|
||||
|
||||
cy.signout();
|
||||
cy.signin(INSTANCE_ADMIN);
|
||||
cy.signinAsAdmin();
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.credentialCard('Credential C3').click();
|
||||
credentialsModal.getters.testSuccessTag().should('be.visible');
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('User Management', { disableAutoLogin: true }, () => {
|
||||
cy.enableFeature('sharing');
|
||||
});
|
||||
|
||||
it.only('should login and logout', () => {
|
||||
it('should login and logout', () => {
|
||||
cy.visit('/');
|
||||
cy.get('input[name="email"]').type(INSTANCE_OWNER.email);
|
||||
cy.get('input[name="password"]').type(INSTANCE_OWNER.password);
|
||||
|
||||
@@ -34,15 +34,12 @@ describe('Canvas Actions', () => {
|
||||
addDefaultSticky();
|
||||
workflowPage.actions.deselectAll();
|
||||
workflowPage.actions.addStickyFromContextMenu();
|
||||
workflowPage.actions.hitAddStickyShortcut();
|
||||
workflowPage.actions.hitAddSticky();
|
||||
|
||||
workflowPage.getters.stickies().should('have.length', 3);
|
||||
|
||||
// Should not add a sticky for ctrl+shift+s
|
||||
cy.get('body')
|
||||
.type(META_KEY, { delay: 500, release: false })
|
||||
.type('{shift}', { release: false })
|
||||
.type('s');
|
||||
cy.get('body').type(`{${META_KEY}+shift+s}`);
|
||||
|
||||
workflowPage.getters.stickies().should('have.length', 3);
|
||||
workflowPage.getters
|
||||
|
||||
@@ -6,13 +6,12 @@ import {
|
||||
getPublicApiUpgradeCTA,
|
||||
} from '../pages';
|
||||
import planData from '../fixtures/Plan_data_opt_in_trial.json';
|
||||
import { INSTANCE_OWNER } from '../constants';
|
||||
|
||||
const mainSidebar = new MainSidebar();
|
||||
const bannerStack = new BannerStack();
|
||||
const workflowPage = new WorkflowPage();
|
||||
|
||||
describe('Cloud', { disableAutoLogin: true }, () => {
|
||||
describe('Cloud', () => {
|
||||
before(() => {
|
||||
const now = new Date();
|
||||
const fiveDaysFromNow = new Date(now.getTime() + 5 * 24 * 60 * 60 * 1000);
|
||||
@@ -20,22 +19,12 @@ describe('Cloud', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.intercept('GET', '/rest/admin/cloud-plan', {
|
||||
body: planData,
|
||||
}).as('getPlanData');
|
||||
|
||||
cy.intercept('GET', '/rest/settings', (req) => {
|
||||
req.on('response', (res) => {
|
||||
res.send({
|
||||
data: {
|
||||
...res.body.data,
|
||||
deployment: { type: 'cloud' },
|
||||
n8nMetadata: { userId: 1 },
|
||||
},
|
||||
});
|
||||
});
|
||||
}).as('loadSettings');
|
||||
|
||||
cy.overrideSettings({
|
||||
deployment: { type: 'cloud' },
|
||||
n8nMetadata: { userId: '1' },
|
||||
});
|
||||
cy.intercept('GET', '/rest/admin/cloud-plan', planData).as('getPlanData');
|
||||
cy.intercept('GET', '/rest/cloud/proxy/user/me', {}).as('getCloudUserInfo');
|
||||
cy.intercept('GET', new RegExp('/rest/projects*')).as('projects');
|
||||
cy.intercept('GET', new RegExp('/rest/roles')).as('roles');
|
||||
});
|
||||
@@ -49,8 +38,6 @@ describe('Cloud', { disableAutoLogin: true }, () => {
|
||||
|
||||
describe('BannerStack', () => {
|
||||
it('should render trial banner for opt-in cloud user', () => {
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
|
||||
visitWorkflowPage();
|
||||
|
||||
bannerStack.getters.banner().should('be.visible');
|
||||
@@ -58,21 +45,11 @@ describe('Cloud', { disableAutoLogin: true }, () => {
|
||||
mainSidebar.actions.signout();
|
||||
|
||||
bannerStack.getters.banner().should('not.be.visible');
|
||||
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
|
||||
visitWorkflowPage();
|
||||
|
||||
bannerStack.getters.banner().should('be.visible');
|
||||
|
||||
mainSidebar.actions.signout();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Admin Home', () => {
|
||||
it('Should show admin button', () => {
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
|
||||
visitWorkflowPage();
|
||||
|
||||
mainSidebar.getters.adminPanel().should('be.visible');
|
||||
@@ -81,8 +58,6 @@ describe('Cloud', { disableAutoLogin: true }, () => {
|
||||
|
||||
describe('Public API', () => {
|
||||
it('Should show upgrade CTA for Public API if user is trialing', () => {
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
|
||||
visitPublicApiPage();
|
||||
cy.wait(['@loadSettings', '@projects', '@roles', '@getPlanData']);
|
||||
|
||||
|
||||
@@ -34,9 +34,8 @@ const signinPage = new SigninPage();
|
||||
const personalSettingsPage = new PersonalSettingsPage();
|
||||
const mainSidebar = new MainSidebar();
|
||||
|
||||
describe('Two-factor authentication', () => {
|
||||
describe('Two-factor authentication', { disableAutoLogin: true }, () => {
|
||||
beforeEach(() => {
|
||||
void Cypress.session.clearAllSavedSessions();
|
||||
cy.request('POST', `${BACKEND_BASE_URL}/rest/e2e/reset`, {
|
||||
owner: user,
|
||||
members: [],
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
HTTP_REQUEST_NODE_NAME,
|
||||
IF_NODE_NAME,
|
||||
INSTANCE_OWNER,
|
||||
MANUAL_TRIGGER_NODE_NAME,
|
||||
EDIT_FIELDS_SET_NODE_NAME,
|
||||
} from '../constants';
|
||||
@@ -21,7 +20,7 @@ describe('Debug', () => {
|
||||
cy.intercept('GET', '/rest/executions/*').as('getExecution');
|
||||
cy.intercept('POST', '/rest/workflows/**/run').as('postWorkflowRun');
|
||||
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
cy.signinAsOwner();
|
||||
|
||||
workflowPage.actions.visit();
|
||||
|
||||
|
||||
@@ -1,55 +1,246 @@
|
||||
import { TemplatesPage } from '../pages/templates';
|
||||
import { WorkflowPage } from '../pages/workflow';
|
||||
import { WorkflowsPage } from '../pages/workflows';
|
||||
import { MainSidebar } from '../pages/sidebar/main-sidebar';
|
||||
import OnboardingWorkflow from '../fixtures/Onboarding_workflow.json';
|
||||
import WorkflowTemplate from '../fixtures/Workflow_template_write_http_query.json';
|
||||
|
||||
const templatesPage = new TemplatesPage();
|
||||
const workflowPage = new WorkflowPage();
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
const mainSidebar = new MainSidebar();
|
||||
|
||||
describe('Workflow templates', () => {
|
||||
beforeEach(() => {
|
||||
cy.intercept('GET', '**/rest/settings', (req) => {
|
||||
// Disable cache
|
||||
delete req.headers['if-none-match'];
|
||||
req.reply((res) => {
|
||||
if (res.body.data) {
|
||||
// Disable custom templates host if it has been overridden by another intercept
|
||||
res.body.data.templates = { enabled: true, host: 'https://api.n8n.io/api/' };
|
||||
}
|
||||
});
|
||||
}).as('settingsRequest');
|
||||
const mockTemplateHost = (host: string) => {
|
||||
cy.overrideSettings({
|
||||
templates: { enabled: true, host },
|
||||
});
|
||||
};
|
||||
|
||||
describe('For api.n8n.io', () => {
|
||||
beforeEach(() => {
|
||||
mockTemplateHost('https://api.n8n.io/api/');
|
||||
});
|
||||
|
||||
it('Opens website when clicking templates sidebar link', () => {
|
||||
cy.visit(workflowsPage.url);
|
||||
mainSidebar.getters.templates().should('be.visible');
|
||||
// Templates should be a link to the website
|
||||
mainSidebar.getters
|
||||
.templates()
|
||||
.parent('a')
|
||||
.should('have.attr', 'href')
|
||||
.and('include', 'https://n8n.io/workflows');
|
||||
// Link should contain instance address and n8n version
|
||||
mainSidebar.getters
|
||||
.templates()
|
||||
.parent('a')
|
||||
.then(($a) => {
|
||||
const href = $a.attr('href');
|
||||
const params = new URLSearchParams(href);
|
||||
// Link should have all mandatory parameters expected on the website
|
||||
expect(decodeURIComponent(`${params.get('utm_instance')}`)).to.include(
|
||||
window.location.origin,
|
||||
);
|
||||
expect(params.get('utm_n8n_version')).to.match(/[0-9]+\.[0-9]+\.[0-9]+/);
|
||||
expect(params.get('utm_awc')).to.match(/[0-9]+/);
|
||||
});
|
||||
mainSidebar.getters.templates().parent('a').should('have.attr', 'target', '_blank');
|
||||
});
|
||||
|
||||
it('Redirects to website when visiting templates page directly', () => {
|
||||
cy.intercept(
|
||||
{
|
||||
hostname: 'n8n.io',
|
||||
pathname: '/workflows',
|
||||
},
|
||||
'Mock Template Page',
|
||||
).as('templatesPage');
|
||||
|
||||
cy.visit(templatesPage.url);
|
||||
|
||||
cy.wait('@templatesPage');
|
||||
});
|
||||
});
|
||||
|
||||
it('Opens website when clicking templates sidebar link', () => {
|
||||
cy.visit(workflowsPage.url);
|
||||
mainSidebar.getters.templates().should('be.visible');
|
||||
// Templates should be a link to the website
|
||||
mainSidebar.getters
|
||||
.templates()
|
||||
.parent('a')
|
||||
.should('have.attr', 'href')
|
||||
.and('include', 'https://n8n.io/workflows');
|
||||
// Link should contain instance address and n8n version
|
||||
mainSidebar.getters
|
||||
.templates()
|
||||
.parent('a')
|
||||
.then(($a) => {
|
||||
const href = $a.attr('href');
|
||||
const params = new URLSearchParams(href);
|
||||
// Link should have all mandatory parameters expected on the website
|
||||
expect(decodeURIComponent(`${params.get('utm_instance')}`)).to.include(
|
||||
window.location.origin,
|
||||
);
|
||||
expect(params.get('utm_n8n_version')).to.match(/[0-9]+\.[0-9]+\.[0-9]+/);
|
||||
expect(params.get('utm_awc')).to.match(/[0-9]+/);
|
||||
});
|
||||
mainSidebar.getters.templates().parent('a').should('have.attr', 'target', '_blank');
|
||||
});
|
||||
describe('For a custom template host', () => {
|
||||
const hostname = 'random.domain';
|
||||
const categories = [
|
||||
{ id: 1, name: 'Engineering' },
|
||||
{ id: 2, name: 'Finance' },
|
||||
{ id: 3, name: 'Sales' },
|
||||
];
|
||||
const collections = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Test Collection',
|
||||
workflows: [{ id: 1 }],
|
||||
nodes: [],
|
||||
},
|
||||
];
|
||||
|
||||
it('Redirects to website when visiting templates page directly', () => {
|
||||
cy.visit(templatesPage.url);
|
||||
cy.origin('https://n8n.io', () => {
|
||||
cy.url().should('include', 'https://n8n.io/workflows');
|
||||
beforeEach(() => {
|
||||
cy.intercept({ hostname, pathname: '/api/health' }, { status: 'OK' });
|
||||
cy.intercept({ hostname, pathname: '/api/templates/categories' }, { categories });
|
||||
cy.intercept(
|
||||
{ hostname, pathname: '/api/templates/collections', query: { category: '**' } },
|
||||
(req) => {
|
||||
req.reply({ collections: req.query['category[]'] === '3' ? [] : collections });
|
||||
},
|
||||
);
|
||||
cy.intercept(
|
||||
{ hostname, pathname: '/api/templates/search', query: { category: '**' } },
|
||||
(req) => {
|
||||
const fixture =
|
||||
req.query.category === 'Sales'
|
||||
? 'templates_search/sales_templates_search_response.json'
|
||||
: 'templates_search/all_templates_search_response.json';
|
||||
req.reply({ statusCode: 200, fixture });
|
||||
},
|
||||
);
|
||||
|
||||
cy.intercept(
|
||||
{ hostname, pathname: '/api/workflows/templates/1' },
|
||||
{
|
||||
statusCode: 200,
|
||||
body: {
|
||||
id: 1,
|
||||
name: OnboardingWorkflow.name,
|
||||
workflow: OnboardingWorkflow,
|
||||
},
|
||||
},
|
||||
).as('getTemplate');
|
||||
|
||||
cy.intercept(
|
||||
{ hostname, pathname: '/api/templates/workflows/1' },
|
||||
{
|
||||
statusCode: 200,
|
||||
body: WorkflowTemplate,
|
||||
},
|
||||
).as('getTemplatePreview');
|
||||
|
||||
mockTemplateHost(`https://${hostname}/api`);
|
||||
});
|
||||
|
||||
it('can open onboarding flow', () => {
|
||||
templatesPage.actions.openOnboardingFlow();
|
||||
cy.url().should('match', /.*\/workflow\/.*?onboardingId=1$/);
|
||||
|
||||
workflowPage.actions.shouldHaveWorkflowName('Demo: ' + OnboardingWorkflow.name);
|
||||
workflowPage.getters.canvasNodes().should('have.length', 4);
|
||||
workflowPage.getters.stickies().should('have.length', 1);
|
||||
workflowPage.getters.canvasNodes().first().should('have.descendants', '.node-pin-data-icon');
|
||||
});
|
||||
|
||||
it('can import template', () => {
|
||||
templatesPage.actions.importTemplate();
|
||||
cy.url().should('include', '/workflow/new?templateId=1');
|
||||
|
||||
workflowPage.getters.canvasNodes().should('have.length', 4);
|
||||
workflowPage.getters.stickies().should('have.length', 1);
|
||||
workflowPage.actions.shouldHaveWorkflowName(OnboardingWorkflow.name);
|
||||
});
|
||||
|
||||
it('should save template id with the workflow', () => {
|
||||
templatesPage.actions.importTemplate();
|
||||
|
||||
cy.visit(templatesPage.url);
|
||||
cy.get('.el-skeleton.n8n-loading').should('not.exist');
|
||||
templatesPage.getters.firstTemplateCard().should('exist');
|
||||
templatesPage.getters.templatesLoadingContainer().should('not.exist');
|
||||
templatesPage.getters.firstTemplateCard().click();
|
||||
cy.url().should('include', '/templates/1');
|
||||
cy.wait('@getTemplatePreview');
|
||||
|
||||
templatesPage.getters.useTemplateButton().click();
|
||||
cy.url().should('include', '/workflow/new');
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
|
||||
workflowPage.actions.hitSelectAll();
|
||||
workflowPage.actions.hitCopy();
|
||||
|
||||
cy.grantBrowserPermissions('clipboardReadWrite', 'clipboardSanitizedWrite');
|
||||
// Check workflow JSON by copying it to clipboard
|
||||
cy.readClipboard().then((workflowJSON) => {
|
||||
expect(workflowJSON).to.contain('"templateId": "1"');
|
||||
});
|
||||
});
|
||||
|
||||
it('can open template with images and hides workflow screenshots', () => {
|
||||
cy.visit(`${templatesPage.url}/1`);
|
||||
cy.wait('@getTemplatePreview');
|
||||
|
||||
templatesPage.getters.description().find('img').should('have.length', 1);
|
||||
});
|
||||
|
||||
it('renders search elements correctly', () => {
|
||||
cy.visit(templatesPage.url);
|
||||
templatesPage.getters.searchInput().should('exist');
|
||||
templatesPage.getters.allCategoriesFilter().should('exist');
|
||||
templatesPage.getters.categoryFilters().should('have.length.greaterThan', 1);
|
||||
templatesPage.getters.templateCards().should('have.length.greaterThan', 0);
|
||||
});
|
||||
|
||||
it('can filter templates by category', () => {
|
||||
cy.visit(templatesPage.url);
|
||||
templatesPage.getters.templatesLoadingContainer().should('not.exist');
|
||||
templatesPage.getters.categoryFilter('sales').should('exist');
|
||||
let initialTemplateCount = 0;
|
||||
let initialCollectionCount = 0;
|
||||
|
||||
templatesPage.getters.templateCountLabel().then(($el) => {
|
||||
initialTemplateCount = parseInt($el.text().replace(/\D/g, ''), 10);
|
||||
templatesPage.getters.collectionCountLabel().then(($el1) => {
|
||||
initialCollectionCount = parseInt($el1.text().replace(/\D/g, ''), 10);
|
||||
|
||||
templatesPage.getters.categoryFilter('sales').click();
|
||||
templatesPage.getters.templatesLoadingContainer().should('not.exist');
|
||||
|
||||
// Should have less templates and collections after selecting a category
|
||||
templatesPage.getters.templateCountLabel().should(($el2) => {
|
||||
expect(parseInt($el2.text().replace(/\D/g, ''), 10)).to.be.lessThan(
|
||||
initialTemplateCount,
|
||||
);
|
||||
});
|
||||
templatesPage.getters.collectionCountLabel().should(($el2) => {
|
||||
expect(parseInt($el2.text().replace(/\D/g, ''), 10)).to.be.lessThan(
|
||||
initialCollectionCount,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should preserve search query in URL', () => {
|
||||
cy.visit(templatesPage.url);
|
||||
templatesPage.getters.templatesLoadingContainer().should('not.exist');
|
||||
templatesPage.getters.categoryFilter('sales').should('exist');
|
||||
templatesPage.getters.categoryFilter('sales').click();
|
||||
templatesPage.getters.searchInput().type('auto');
|
||||
|
||||
cy.url().should('include', '?categories=');
|
||||
cy.url().should('include', '&search=');
|
||||
|
||||
cy.reload();
|
||||
|
||||
// Should preserve search query in URL
|
||||
cy.url().should('include', '?categories=');
|
||||
cy.url().should('include', '&search=');
|
||||
|
||||
// Sales category should still be selected
|
||||
templatesPage.getters
|
||||
.categoryFilter('sales')
|
||||
.find('label')
|
||||
.should('have.class', 'is-checked');
|
||||
// Search input should still have the search query
|
||||
templatesPage.getters.searchInput().should('have.value', 'auto');
|
||||
// Sales checkbox should be pushed to the top
|
||||
templatesPage.getters
|
||||
.categoryFilters()
|
||||
.eq(1)
|
||||
.then(($el) => {
|
||||
expect($el.text()).to.equal('Sales');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@ import {
|
||||
CODE_NODE_NAME,
|
||||
EDIT_FIELDS_SET_NODE_NAME,
|
||||
IF_NODE_NAME,
|
||||
INSTANCE_OWNER,
|
||||
SCHEDULE_TRIGGER_NODE_NAME,
|
||||
} from '../constants';
|
||||
import {
|
||||
@@ -125,7 +124,7 @@ describe('Editor actions should work', () => {
|
||||
beforeEach(() => {
|
||||
cy.enableFeature('debugInEditor');
|
||||
cy.enableFeature('workflowHistory');
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
cy.signinAsOwner();
|
||||
createNewWorkflowAndActivate();
|
||||
});
|
||||
|
||||
@@ -186,7 +185,7 @@ describe('Editor zoom should work after route changes', () => {
|
||||
beforeEach(() => {
|
||||
cy.enableFeature('debugInEditor');
|
||||
cy.enableFeature('workflowHistory');
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
cy.signinAsOwner();
|
||||
workflowPage.actions.visit();
|
||||
cy.createFixtureWorkflow('Lots_of_nodes.json', 'Lots of nodes');
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { INSTANCE_MEMBERS, INSTANCE_OWNER } from '../constants';
|
||||
import { WorkerViewPage } from '../pages';
|
||||
|
||||
const workerViewPage = new WorkerViewPage();
|
||||
@@ -10,13 +9,13 @@ describe('Worker View (unlicensed)', () => {
|
||||
});
|
||||
|
||||
it('should not show up in the menu sidebar', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
cy.visit(workerViewPage.url);
|
||||
workerViewPage.getters.menuItem().should('not.exist');
|
||||
});
|
||||
|
||||
it('should show action box', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
cy.visit(workerViewPage.url);
|
||||
workerViewPage.getters.workerViewUnlicensed().should('exist');
|
||||
});
|
||||
@@ -29,14 +28,14 @@ describe('Worker View (licensed)', () => {
|
||||
});
|
||||
|
||||
it('should show up in the menu sidebar', () => {
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
cy.signinAsOwner();
|
||||
cy.enableQueueMode();
|
||||
cy.visit(workerViewPage.url);
|
||||
workerViewPage.getters.menuItem().should('exist');
|
||||
});
|
||||
|
||||
it('should show worker list view', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
cy.visit(workerViewPage.url);
|
||||
workerViewPage.getters.workerViewLicensed().should('exist');
|
||||
});
|
||||
|
||||
@@ -8,10 +8,19 @@ import { WorkflowPage } from '../pages/workflow';
|
||||
import * as formStep from '../composables/setup-template-form-step';
|
||||
import { getSetupWorkflowCredentialsButton } from '../composables/setup-workflow-credentials-button';
|
||||
import * as setupCredsModal from '../composables/modals/workflow-credential-setup-modal';
|
||||
import TestTemplate1 from '../fixtures/Test_Template_1.json';
|
||||
import TestTemplate2 from '../fixtures/Test_Template_2.json';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
|
||||
const testTemplate = templateCredentialsSetupPage.testData.simpleTemplate;
|
||||
const testTemplate = {
|
||||
id: 1205,
|
||||
data: TestTemplate1,
|
||||
};
|
||||
const templateWithoutCredentials = {
|
||||
id: 1344,
|
||||
data: TestTemplate2,
|
||||
};
|
||||
|
||||
// NodeView uses beforeunload listener that will show a browser
|
||||
// native popup, which will block cypress from continuing / exiting.
|
||||
@@ -29,19 +38,19 @@ Cypress.on('window:before:load', (win) => {
|
||||
|
||||
describe('Template credentials setup', () => {
|
||||
beforeEach(() => {
|
||||
cy.intercept('GET', `https://api.n8n.io/api/templates/workflows/${testTemplate.id}`, {
|
||||
fixture: testTemplate.fixture,
|
||||
cy.intercept(
|
||||
'GET',
|
||||
`https://api.n8n.io/api/templates/workflows/${testTemplate.id}`,
|
||||
testTemplate.data,
|
||||
).as('getTemplatePreview');
|
||||
cy.intercept(
|
||||
'GET',
|
||||
`https://api.n8n.io/api/workflows/templates/${testTemplate.id}`,
|
||||
testTemplate.data.workflow,
|
||||
).as('getTemplate');
|
||||
cy.overrideSettings({
|
||||
templates: { enabled: true, host: 'https://api.n8n.io/api/' },
|
||||
});
|
||||
cy.intercept('GET', '**/rest/settings', (req) => {
|
||||
// Disable cache
|
||||
delete req.headers['if-none-match'];
|
||||
req.reply((res) => {
|
||||
if (res.body.data) {
|
||||
// Disable custom templates host if it has been overridden by another intercept
|
||||
res.body.data.templates = { enabled: true, host: 'https://api.n8n.io/api/' };
|
||||
}
|
||||
});
|
||||
}).as('settingsRequest');
|
||||
});
|
||||
|
||||
it('can be opened from template collection page', () => {
|
||||
@@ -108,7 +117,7 @@ describe('Template credentials setup', () => {
|
||||
|
||||
// Focus the canvas so the copy to clipboard works
|
||||
workflowPage.getters.canvasNodes().eq(0).realClick();
|
||||
workflowPage.actions.selectAll();
|
||||
workflowPage.actions.hitSelectAll();
|
||||
workflowPage.actions.hitCopy();
|
||||
|
||||
cy.grantBrowserPermissions('clipboardReadWrite', 'clipboardSanitizedWrite');
|
||||
@@ -125,11 +134,9 @@ describe('Template credentials setup', () => {
|
||||
});
|
||||
|
||||
it('should work with a template that has no credentials (ADO-1603)', () => {
|
||||
const templateWithoutCreds = templateCredentialsSetupPage.testData.templateWithoutCredentials;
|
||||
cy.intercept('GET', `https://api.n8n.io/api/templates/workflows/${templateWithoutCreds.id}`, {
|
||||
fixture: templateWithoutCreds.fixture,
|
||||
});
|
||||
templateCredentialsSetupPage.visitTemplateCredentialSetupPage(templateWithoutCreds.id);
|
||||
const { id, data } = templateWithoutCredentials;
|
||||
cy.intercept('GET', `https://api.n8n.io/api/templates/workflows/${id}`, data);
|
||||
templateCredentialsSetupPage.visitTemplateCredentialSetupPage(id);
|
||||
|
||||
const expectedAppNames = ['1. Email (IMAP)', '2. Nextcloud'];
|
||||
const expectedAppDescriptions = [
|
||||
@@ -152,7 +159,7 @@ describe('Template credentials setup', () => {
|
||||
workflowPage.getters.canvasNodes().should('have.length', 3);
|
||||
});
|
||||
|
||||
describe('Credential setup from workflow editor', () => {
|
||||
describe('Credential setup from workflow editor', { disableAutoLogin: true }, () => {
|
||||
beforeEach(() => {
|
||||
cy.resetDatabase();
|
||||
cy.signinAsOwner();
|
||||
@@ -190,7 +197,7 @@ describe('Template credentials setup', () => {
|
||||
|
||||
// Focus the canvas so the copy to clipboard works
|
||||
workflowPage.getters.canvasNodes().eq(0).realClick();
|
||||
workflowPage.actions.selectAll();
|
||||
workflowPage.actions.hitSelectAll();
|
||||
workflowPage.actions.hitCopy();
|
||||
|
||||
cy.grantBrowserPermissions('clipboardReadWrite', 'clipboardSanitizedWrite');
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { INSTANCE_ADMIN, INSTANCE_OWNER } from '../constants';
|
||||
import { SettingsPage } from '../pages/settings';
|
||||
|
||||
const settingsPage = new SettingsPage();
|
||||
|
||||
describe('Admin user', { disableAutoLogin: true }, () => {
|
||||
it('should see same Settings sub menu items as instance owner', () => {
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
cy.signinAsOwner();
|
||||
cy.visit(settingsPage.url);
|
||||
|
||||
let ownerMenuItems = 0;
|
||||
@@ -15,7 +14,7 @@ describe('Admin user', { disableAutoLogin: true }, () => {
|
||||
});
|
||||
|
||||
cy.signout();
|
||||
cy.signin(INSTANCE_ADMIN);
|
||||
cy.signinAsAdmin();
|
||||
cy.visit(settingsPage.url);
|
||||
|
||||
settingsPage.getters.menuItems().should('have.length', ownerMenuItems);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { INSTANCE_OWNER } from '../constants';
|
||||
import { WorkflowsPage } from '../pages/workflows';
|
||||
import {
|
||||
closeVersionUpdatesPanel,
|
||||
@@ -11,52 +10,18 @@ const workflowsPage = new WorkflowsPage();
|
||||
|
||||
describe('Versions', () => {
|
||||
it('should open updates panel', () => {
|
||||
cy.intercept('GET', '/rest/settings', (req) => {
|
||||
req.continue((res) => {
|
||||
if (res.body.hasOwnProperty('data')) {
|
||||
res.body.data = {
|
||||
...res.body.data,
|
||||
releaseChannel: 'stable',
|
||||
versionCli: '1.0.0',
|
||||
versionNotifications: {
|
||||
enabled: true,
|
||||
endpoint: 'https://api.n8n.io/api/versions/',
|
||||
infoUrl: 'https://docs.n8n.io/getting-started/installation/updating.html',
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
}).as('settings');
|
||||
|
||||
cy.intercept('GET', 'https://api.n8n.io/api/versions/1.0.0', [
|
||||
{
|
||||
name: '1.3.1',
|
||||
createdAt: '2023-08-18T11:53:12.857Z',
|
||||
hasSecurityIssue: null,
|
||||
hasSecurityFix: null,
|
||||
securityIssueFixVersion: null,
|
||||
hasBreakingChange: null,
|
||||
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n131',
|
||||
nodes: [],
|
||||
description: 'Includes <strong>bug fixes</strong>',
|
||||
cy.overrideSettings({
|
||||
releaseChannel: 'stable',
|
||||
versionCli: '1.0.0',
|
||||
versionNotifications: {
|
||||
enabled: true,
|
||||
endpoint: 'https://api.n8n.io/api/versions/',
|
||||
infoUrl: 'https://docs.n8n.io/getting-started/installation/updating.html',
|
||||
},
|
||||
{
|
||||
name: '1.0.5',
|
||||
createdAt: '2023-07-24T10:54:56.097Z',
|
||||
hasSecurityIssue: false,
|
||||
hasSecurityFix: null,
|
||||
securityIssueFixVersion: null,
|
||||
hasBreakingChange: true,
|
||||
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n104',
|
||||
nodes: [],
|
||||
description: 'Includes <strong>core functionality</strong> and <strong>bug fixes</strong>',
|
||||
},
|
||||
]);
|
||||
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
});
|
||||
|
||||
cy.visit(workflowsPage.url);
|
||||
cy.wait('@settings');
|
||||
cy.wait('@loadSettings');
|
||||
|
||||
getVersionUpdatesPanelOpenButton().should('contain', '2 updates');
|
||||
openVersionUpdatesPanel();
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
INSTANCE_ADMIN,
|
||||
INSTANCE_MEMBERS,
|
||||
INSTANCE_OWNER,
|
||||
MANUAL_TRIGGER_NODE_NAME,
|
||||
NOTION_NODE_NAME,
|
||||
} from '../constants';
|
||||
import { INSTANCE_MEMBERS, MANUAL_TRIGGER_NODE_NAME, NOTION_NODE_NAME } from '../constants';
|
||||
import {
|
||||
WorkflowsPage,
|
||||
WorkflowPage,
|
||||
@@ -23,7 +17,7 @@ const credentialsModal = new CredentialsModal();
|
||||
const executionsTab = new WorkflowExecutionsTab();
|
||||
const ndv = new NDV();
|
||||
|
||||
describe('Projects', () => {
|
||||
describe('Projects', { disableAutoLogin: true }, () => {
|
||||
before(() => {
|
||||
cy.resetDatabase();
|
||||
cy.enableFeature('sharing');
|
||||
@@ -34,7 +28,7 @@ describe('Projects', () => {
|
||||
});
|
||||
|
||||
it('should handle workflows and credentials and menu items', () => {
|
||||
cy.signin(INSTANCE_ADMIN);
|
||||
cy.signinAsAdmin();
|
||||
cy.visit(workflowsPage.url);
|
||||
workflowsPage.getters.workflowCards().should('not.have.length');
|
||||
|
||||
@@ -230,8 +224,7 @@ describe('Projects', () => {
|
||||
});
|
||||
|
||||
it('should not show project add button and projects to a member if not invited to any project', () => {
|
||||
cy.signout();
|
||||
cy.signin(INSTANCE_MEMBERS[1]);
|
||||
cy.signinAsMember(1);
|
||||
cy.visit(workflowsPage.url);
|
||||
|
||||
projects.getAddProjectButton().should('not.exist');
|
||||
@@ -249,7 +242,7 @@ describe('Projects', () => {
|
||||
});
|
||||
|
||||
it('should filter credentials by project ID when creating new workflow or hard reloading an opened workflow', () => {
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
cy.signinAsOwner();
|
||||
cy.visit(workflowsPage.url);
|
||||
|
||||
// Create a project and add a credential to it
|
||||
|
||||
@@ -345,7 +345,7 @@ describe('NDV', () => {
|
||||
ndv.getters.parameterInput('remoteOptions').click();
|
||||
getVisibleSelect().find('.el-select-dropdown__item').should('have.length', 3);
|
||||
|
||||
ndv.actions.setInvalidExpression({ fieldName: 'fieldId', delay: 200 });
|
||||
ndv.actions.setInvalidExpression({ fieldName: 'fieldId' });
|
||||
|
||||
ndv.getters.inputPanel().click(); // remove focus from input, hide expression preview
|
||||
|
||||
@@ -363,7 +363,7 @@ describe('NDV', () => {
|
||||
getVisibleSelect().find('.el-select-dropdown__item').should('have.length', 3);
|
||||
ndv.getters.parameterInput('remoteOptions').click();
|
||||
|
||||
ndv.actions.setInvalidExpression({ fieldName: 'otherField', delay: 50 });
|
||||
ndv.actions.setInvalidExpression({ fieldName: 'otherField' });
|
||||
|
||||
ndv.getters.nodeParameters().click(); // remove focus from input, hide expression preview
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
CODE_NODE_NAME,
|
||||
MANUAL_TRIGGER_NODE_NAME,
|
||||
META_KEY,
|
||||
SCHEDULE_TRIGGER_NODE_NAME,
|
||||
EDIT_FIELDS_SET_NODE_NAME,
|
||||
INSTANCE_MEMBERS,
|
||||
INSTANCE_OWNER,
|
||||
NOTION_NODE_NAME,
|
||||
} from '../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
@@ -136,13 +133,13 @@ describe('Workflow Actions', () => {
|
||||
);
|
||||
cy.reload();
|
||||
cy.get('.el-loading-mask').should('exist');
|
||||
cy.get('body').type(META_KEY, { release: false }).type('s');
|
||||
cy.get('body').type(META_KEY, { release: false }).type('s');
|
||||
cy.get('body').type(META_KEY, { release: false }).type('s');
|
||||
WorkflowPage.actions.hitSaveWorkflow();
|
||||
WorkflowPage.actions.hitSaveWorkflow();
|
||||
WorkflowPage.actions.hitSaveWorkflow();
|
||||
cy.wrap(null).then(() => expect(interceptCalledCount).to.eq(0));
|
||||
cy.waitForLoad();
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
cy.get('body').type(META_KEY, { release: false }).type('s');
|
||||
WorkflowPage.actions.hitSaveWorkflow();
|
||||
cy.wait('@saveWorkflow');
|
||||
cy.wrap(null).then(() => expect(interceptCalledCount).to.eq(1));
|
||||
});
|
||||
@@ -172,9 +169,10 @@ describe('Workflow Actions', () => {
|
||||
WorkflowPage.getters.canvasNodes().should('have.have.length', 2);
|
||||
|
||||
cy.get('#node-creator').should('not.exist');
|
||||
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('a');
|
||||
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
cy.get('.jtk-drag-selected').should('have.length', 2);
|
||||
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('c');
|
||||
WorkflowPage.actions.hitCopy();
|
||||
successToast().should('exist');
|
||||
});
|
||||
|
||||
@@ -338,33 +336,32 @@ describe('Workflow Actions', () => {
|
||||
it('should run workflow using keyboard shortcut', () => {
|
||||
WorkflowPage.actions.addInitialNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.saveWorkflowOnButtonClick();
|
||||
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('{enter}');
|
||||
WorkflowPage.actions.hitExecuteWorkflow();
|
||||
successToast().should('contain.text', 'Workflow executed successfully');
|
||||
});
|
||||
|
||||
it('should not run empty workflows', () => {
|
||||
// Clear the canvas
|
||||
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('a');
|
||||
cy.get('body').type('{backspace}');
|
||||
WorkflowPage.actions.hitDeleteAllNodes();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 0);
|
||||
// Button should be disabled
|
||||
WorkflowPage.getters.executeWorkflowButton().should('be.disabled');
|
||||
// Keyboard shortcut should not work
|
||||
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('{enter}');
|
||||
WorkflowPage.actions.hitExecuteWorkflow();
|
||||
successToast().should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Menu entry Push To Git', () => {
|
||||
it('should not show up in the menu for members', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signinAsMember(0);
|
||||
cy.visit(WorkflowPages.url);
|
||||
WorkflowPage.actions.visit();
|
||||
WorkflowPage.getters.workflowMenuItemGitPush().should('not.exist');
|
||||
});
|
||||
|
||||
it('should show up for owners', () => {
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
cy.signinAsOwner();
|
||||
cy.visit(WorkflowPages.url);
|
||||
WorkflowPage.actions.visit();
|
||||
WorkflowPage.getters.workflowMenuItemGitPush().should('exist');
|
||||
|
||||
Reference in New Issue
Block a user