mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
ci: Refactor e2e tests to delete boilerplate code (no-changelog) (#6524)
This commit is contained in:
committed by
GitHub
parent
abe7f71627
commit
0e071724ee
@@ -1,9 +1,32 @@
|
||||
export const BACKEND_BASE_URL = 'http://localhost:5678';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
|
||||
export const BASE_URL = 'http://localhost:5678';
|
||||
export const BACKEND_BASE_URL = 'http://localhost:5678';
|
||||
export const N8N_AUTH_COOKIE = 'n8n-auth';
|
||||
|
||||
export const DEFAULT_USER_EMAIL = 'nathan@n8n.io';
|
||||
export const DEFAULT_USER_PASSWORD = 'CypressTest123';
|
||||
const DEFAULT_USER_PASSWORD = 'CypressTest123';
|
||||
|
||||
export const INSTANCE_OWNER = {
|
||||
email: 'nathan@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
};
|
||||
|
||||
export const INSTANCE_MEMBERS = [
|
||||
{
|
||||
email: 'rebecca@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
},
|
||||
{
|
||||
email: 'mustafa@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
},
|
||||
];
|
||||
|
||||
export const MANUAL_TRIGGER_NODE_NAME = 'Manual Trigger';
|
||||
export const MANUAL_TRIGGER_NODE_DISPLAY_NAME = 'When clicking "Execute Workflow"';
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Authentication', () => {
|
||||
beforeEach(() => {
|
||||
cy.resetAll();
|
||||
});
|
||||
|
||||
it('should setup owner', () => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
it('should sign user in', () => {
|
||||
cy.setupOwner({ email, password, firstName, lastName });
|
||||
cy.on('uncaught:exception', (err, runnable) => {
|
||||
expect(err.message).to.include('Not logged in');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
cy.signin({ email, password });
|
||||
});
|
||||
});
|
||||
@@ -1,26 +1,14 @@
|
||||
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
|
||||
const WorkflowsPage = new WorkflowsPageClass();
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
|
||||
const multipleWorkflowsCount = 5;
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Workflows', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
cy.visit(WorkflowsPage.url);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { SettingsLogStreamingPage } from '../pages';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
const settingsLogStreamingPage = new SettingsLogStreamingPage();
|
||||
|
||||
describe('Log Streaming Settings', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
});
|
||||
|
||||
it('should show the unlicensed view when the feature is disabled', () => {
|
||||
cy.visit('/settings/log-streaming');
|
||||
settingsLogStreamingPage.getters.getActionBoxUnlicensed().should('be.visible');
|
||||
@@ -25,7 +11,7 @@ describe('Log Streaming Settings', () => {
|
||||
});
|
||||
|
||||
it('should show the licensed view when the feature is enabled', () => {
|
||||
cy.enableFeature('feat:logStreaming');
|
||||
cy.enableFeature('logStreaming');
|
||||
cy.visit('/settings/log-streaming');
|
||||
settingsLogStreamingPage.getters.getActionBoxLicensed().should('be.visible');
|
||||
settingsLogStreamingPage.getters.getAddFirstDestinationButton().should('be.visible');
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { CODE_NODE_NAME, DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD, SET_NODE_NAME } from './../constants';
|
||||
import { CODE_NODE_NAME, SET_NODE_NAME } from './../constants';
|
||||
import { SCHEDULE_TRIGGER_NODE_NAME } from '../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { NDV } from '../pages/ndv';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
|
||||
// Suite-specific constants
|
||||
const CODE_NODE_NEW_NAME = 'Something else';
|
||||
@@ -10,18 +9,8 @@ const CODE_NODE_NEW_NAME = 'Something else';
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Undo/Redo', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
|
||||
describe('Inline expression editor', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
WorkflowPage.actions.addInitialNodeToCanvas('Manual');
|
||||
WorkflowPage.actions.addNodeToCanvas('Hacker News');
|
||||
|
||||
@@ -6,25 +6,12 @@ import {
|
||||
SET_NODE_NAME,
|
||||
IF_NODE_NAME,
|
||||
HTTP_REQUEST_NODE_NAME,
|
||||
DEFAULT_USER_EMAIL,
|
||||
DEFAULT_USER_PASSWORD,
|
||||
} from './../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
describe('Canvas Actions', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -5,14 +5,9 @@ import {
|
||||
SCHEDULE_TRIGGER_NODE_NAME,
|
||||
SET_NODE_NAME,
|
||||
SWITCH_NODE_NAME,
|
||||
IF_NODE_NAME,
|
||||
MERGE_NODE_NAME,
|
||||
HTTP_REQUEST_NODE_NAME,
|
||||
DEFAULT_USER_EMAIL,
|
||||
DEFAULT_USER_PASSWORD,
|
||||
} from './../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
|
||||
@@ -23,18 +18,8 @@ const ZOOM_OUT_X1_FACTOR = 0.8;
|
||||
const ZOOM_OUT_X2_FACTOR = 0.64;
|
||||
const RENAME_NODE_NAME = 'Something else';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Canvas Node Manipulation and Navigation', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import {
|
||||
DEFAULT_USER_EMAIL,
|
||||
DEFAULT_USER_PASSWORD,
|
||||
HTTP_REQUEST_NODE_NAME,
|
||||
MANUAL_TRIGGER_NODE_NAME,
|
||||
PIPEDRIVE_NODE_NAME,
|
||||
@@ -12,18 +9,8 @@ import { WorkflowPage, NDV } from '../pages';
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Data pinning', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
|
||||
const wf = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Data transformation expressions', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
wf.actions.visit();
|
||||
|
||||
cy.window().then(
|
||||
|
||||
@@ -2,27 +2,14 @@ import {
|
||||
MANUAL_TRIGGER_NODE_NAME,
|
||||
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
|
||||
SCHEDULE_TRIGGER_NODE_NAME,
|
||||
DEFAULT_USER_EMAIL,
|
||||
DEFAULT_USER_PASSWORD,
|
||||
} from './../constants';
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Data mapping', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
|
||||
cy.window().then((win) => {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage, WorkflowsPage, NDV } from '../pages';
|
||||
import { BACKEND_BASE_URL } from '../constants';
|
||||
|
||||
@@ -7,18 +5,8 @@ const workflowsPage = new WorkflowsPage();
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Schedule Trigger node', async () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -2,13 +2,6 @@ import { WorkflowPage, NDV, CredentialsModal } from '../pages';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { cowBase64 } from '../support/binaryTestFiles';
|
||||
import { BACKEND_BASE_URL } from '../constants';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
@@ -99,12 +92,7 @@ const simpleWebhookCall = (options: SimpleWebhookCallOptions) => {
|
||||
};
|
||||
|
||||
describe('Webhook Trigger node', async () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
|
||||
cy.window().then((win) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { INSTANCE_MEMBERS, INSTANCE_OWNER } from '../constants';
|
||||
import {
|
||||
CredentialsModal,
|
||||
CredentialsPage,
|
||||
@@ -28,47 +28,12 @@ const workflowPage = new WorkflowPage();
|
||||
const workflowSharingModal = new WorkflowSharingModal();
|
||||
const ndv = new NDV();
|
||||
|
||||
const instanceOwner = {
|
||||
email: `${DEFAULT_USER_EMAIL}one`,
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: 'User',
|
||||
lastName: 'U1',
|
||||
};
|
||||
|
||||
const users = [
|
||||
{
|
||||
email: `${DEFAULT_USER_EMAIL}two`,
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: 'User',
|
||||
lastName: 'U2',
|
||||
},
|
||||
{
|
||||
email: `${DEFAULT_USER_EMAIL}three`,
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: 'User',
|
||||
lastName: 'U3',
|
||||
},
|
||||
];
|
||||
|
||||
describe('Sharing', () => {
|
||||
before(() => {
|
||||
cy.setupOwner(instanceOwner);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err, runnable) => {
|
||||
expect(err.message).to.include('Not logged in');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
it('should invite User U2 and User U3 to instance', () => {
|
||||
cy.inviteUsers({ instanceOwner, users });
|
||||
});
|
||||
describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
before(() => cy.enableFeature('sharing', true));
|
||||
|
||||
let workflowW2Url = '';
|
||||
it('should create C1, W1, W2, share W1 with U3, as U2', () => {
|
||||
cy.signin(users[0]);
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.emptyListCreateCredentialButton().click();
|
||||
@@ -87,7 +52,7 @@ describe('Sharing', () => {
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openShareModal();
|
||||
workflowSharingModal.actions.addUser(users[1].email);
|
||||
workflowSharingModal.actions.addUser(INSTANCE_MEMBERS[1].email);
|
||||
workflowSharingModal.actions.save();
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
|
||||
@@ -100,7 +65,7 @@ describe('Sharing', () => {
|
||||
});
|
||||
|
||||
it('should create C2, share C2 with U1 and U2, as U3', () => {
|
||||
cy.signin(users[1]);
|
||||
cy.signin(INSTANCE_MEMBERS[1]);
|
||||
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.emptyListCreateCredentialButton().click();
|
||||
@@ -109,14 +74,14 @@ describe('Sharing', () => {
|
||||
credentialsModal.getters.connectionParameter('API Key').type('1234567890');
|
||||
credentialsModal.actions.setName('Credential C2');
|
||||
credentialsModal.actions.changeTab('Sharing');
|
||||
credentialsModal.actions.addUser(instanceOwner.email);
|
||||
credentialsModal.actions.addUser(users[0].email);
|
||||
credentialsModal.actions.addUser(INSTANCE_OWNER.email);
|
||||
credentialsModal.actions.addUser(INSTANCE_MEMBERS[0].email);
|
||||
credentialsModal.actions.save();
|
||||
credentialsModal.actions.close();
|
||||
});
|
||||
|
||||
it('should open W1, add node using C2 as U3', () => {
|
||||
cy.signin(users[1]);
|
||||
cy.signin(INSTANCE_MEMBERS[1]);
|
||||
|
||||
cy.visit(workflowsPage.url);
|
||||
workflowsPage.getters.workflowCards().should('have.length', 1);
|
||||
@@ -136,7 +101,7 @@ describe('Sharing', () => {
|
||||
});
|
||||
|
||||
it('should not have access to W2, as U3', () => {
|
||||
cy.signin(users[1]);
|
||||
cy.signin(INSTANCE_MEMBERS[1]);
|
||||
|
||||
cy.visit(workflowW2Url);
|
||||
cy.waitForLoad();
|
||||
@@ -145,7 +110,7 @@ describe('Sharing', () => {
|
||||
});
|
||||
|
||||
it('should have access to W1, W2, as U1', () => {
|
||||
cy.signin(instanceOwner);
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
|
||||
cy.visit(workflowsPage.url);
|
||||
workflowsPage.getters.workflowCards().should('have.length', 2);
|
||||
@@ -165,7 +130,7 @@ describe('Sharing', () => {
|
||||
});
|
||||
|
||||
it('should automatically test C2 when opened by U2 sharee', () => {
|
||||
cy.signin(users[0]);
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
|
||||
cy.visit(credentialsPage.url);
|
||||
credentialsPage.getters.credentialCard('Credential C2').click();
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage } from '../pages';
|
||||
|
||||
const wf = new WorkflowPage();
|
||||
|
||||
const TEST_TAGS = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4', 'Tag 5'];
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Workflow tags', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
wf.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { MainSidebar } from './../pages/sidebar/main-sidebar';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { SettingsSidebar, SettingsUsersPage, WorkflowPage, WorkflowsPage } from '../pages';
|
||||
import { INSTANCE_MEMBERS, INSTANCE_OWNER } from '../constants';
|
||||
import { SettingsUsersPage, WorkflowPage } from '../pages';
|
||||
import { PersonalSettingsPage } from '../pages/settings-personal';
|
||||
|
||||
/**
|
||||
@@ -15,28 +14,6 @@ import { PersonalSettingsPage } from '../pages/settings-personal';
|
||||
* C2 - Credential owned by User C, shared with User A and User B
|
||||
*/
|
||||
|
||||
const instanceOwner = {
|
||||
email: `${DEFAULT_USER_EMAIL}A`,
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: 'User',
|
||||
lastName: 'A',
|
||||
};
|
||||
|
||||
const users = [
|
||||
{
|
||||
email: `${DEFAULT_USER_EMAIL}B`,
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: 'User',
|
||||
lastName: 'B',
|
||||
},
|
||||
{
|
||||
email: `${DEFAULT_USER_EMAIL}C`,
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: 'User',
|
||||
lastName: 'C',
|
||||
},
|
||||
];
|
||||
|
||||
const updatedPersonalData = {
|
||||
newFirstName: 'Something',
|
||||
newLastName: 'Else',
|
||||
@@ -49,47 +26,38 @@ const usersSettingsPage = new SettingsUsersPage();
|
||||
const workflowPage = new WorkflowPage();
|
||||
const personalSettingsPage = new PersonalSettingsPage();
|
||||
|
||||
describe('User Management', () => {
|
||||
before(() => {
|
||||
cy.setupOwner(instanceOwner);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err, runnable) => {
|
||||
expect(err.message).to.include('Not logged in');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
it(`should invite User B and User C to instance`, () => {
|
||||
cy.inviteUsers({ instanceOwner, users });
|
||||
});
|
||||
describe('User Management', { disableAutoLogin: true }, () => {
|
||||
before(() => cy.enableFeature('sharing'));
|
||||
|
||||
it('should prevent non-owners to access UM settings', () => {
|
||||
usersSettingsPage.actions.loginAndVisit(users[0].email, users[0].password, false);
|
||||
usersSettingsPage.actions.loginAndVisit(
|
||||
INSTANCE_MEMBERS[0].email,
|
||||
INSTANCE_MEMBERS[0].password,
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('should allow instance owner to access UM settings', () => {
|
||||
usersSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password, true);
|
||||
usersSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password, true);
|
||||
});
|
||||
|
||||
it('should properly render UM settings page for instance owners', () => {
|
||||
usersSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password, true);
|
||||
usersSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password, true);
|
||||
// All items in user list should be there
|
||||
usersSettingsPage.getters.userListItems().should('have.length', 3);
|
||||
// List item for current user should have the `Owner` badge
|
||||
usersSettingsPage.getters
|
||||
.userItem(instanceOwner.email)
|
||||
.userItem(INSTANCE_OWNER.email)
|
||||
.find('.n8n-badge:contains("Owner")')
|
||||
.should('exist');
|
||||
// Other users list items should contain action pop-up list
|
||||
usersSettingsPage.getters.userActionsToggle(users[0].email).should('exist');
|
||||
usersSettingsPage.getters.userActionsToggle(users[1].email).should('exist');
|
||||
usersSettingsPage.getters.userActionsToggle(INSTANCE_MEMBERS[0].email).should('exist');
|
||||
usersSettingsPage.getters.userActionsToggle(INSTANCE_MEMBERS[1].email).should('exist');
|
||||
});
|
||||
|
||||
it('should delete user and their data', () => {
|
||||
usersSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password, true);
|
||||
usersSettingsPage.actions.opedDeleteDialog(users[0].email);
|
||||
usersSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password, true);
|
||||
usersSettingsPage.actions.opedDeleteDialog(INSTANCE_MEMBERS[0].email);
|
||||
usersSettingsPage.getters.deleteDataRadioButton().realClick();
|
||||
usersSettingsPage.getters.deleteDataInput().type('delete all data');
|
||||
usersSettingsPage.getters.deleteUserButton().realClick();
|
||||
@@ -97,8 +65,8 @@ describe('User Management', () => {
|
||||
});
|
||||
|
||||
it('should delete user and transfer their data', () => {
|
||||
usersSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password, true);
|
||||
usersSettingsPage.actions.opedDeleteDialog(users[1].email);
|
||||
usersSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password, true);
|
||||
usersSettingsPage.actions.opedDeleteDialog(INSTANCE_MEMBERS[1].email);
|
||||
usersSettingsPage.getters.transferDataRadioButton().realClick();
|
||||
usersSettingsPage.getters.userSelectDropDown().realClick();
|
||||
usersSettingsPage.getters.userSelectOptions().first().realClick();
|
||||
@@ -107,7 +75,7 @@ describe('User Management', () => {
|
||||
});
|
||||
|
||||
it(`should allow user to change their personal data`, () => {
|
||||
personalSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password);
|
||||
personalSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password);
|
||||
personalSettingsPage.actions.updateFirstAndLastName(
|
||||
updatedPersonalData.newFirstName,
|
||||
updatedPersonalData.newLastName,
|
||||
@@ -119,14 +87,14 @@ describe('User Management', () => {
|
||||
});
|
||||
|
||||
it(`shouldn't allow user to set weak password`, () => {
|
||||
personalSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password);
|
||||
personalSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password);
|
||||
for (let weakPass of updatedPersonalData.invalidPasswords) {
|
||||
personalSettingsPage.actions.tryToSetWeakPassword(instanceOwner.password, weakPass);
|
||||
personalSettingsPage.actions.tryToSetWeakPassword(INSTANCE_OWNER.password, weakPass);
|
||||
}
|
||||
});
|
||||
|
||||
it(`shouldn't allow user to change password if old password is wrong`, () => {
|
||||
personalSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password);
|
||||
personalSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password);
|
||||
personalSettingsPage.actions.updatePassword('iCannotRemember', updatedPersonalData.newPassword);
|
||||
workflowPage.getters
|
||||
.errorToast()
|
||||
@@ -135,21 +103,21 @@ describe('User Management', () => {
|
||||
});
|
||||
|
||||
it(`should change current user password`, () => {
|
||||
personalSettingsPage.actions.loginAndVisit(instanceOwner.email, instanceOwner.password);
|
||||
personalSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password);
|
||||
personalSettingsPage.actions.updatePassword(
|
||||
instanceOwner.password,
|
||||
INSTANCE_OWNER.password,
|
||||
updatedPersonalData.newPassword,
|
||||
);
|
||||
workflowPage.getters.successToast().should('contain', 'Password updated');
|
||||
personalSettingsPage.actions.loginWithNewData(
|
||||
instanceOwner.email,
|
||||
INSTANCE_OWNER.email,
|
||||
updatedPersonalData.newPassword,
|
||||
);
|
||||
});
|
||||
|
||||
it(`shouldn't allow users to set invalid email`, () => {
|
||||
personalSettingsPage.actions.loginAndVisit(
|
||||
instanceOwner.email,
|
||||
INSTANCE_OWNER.email,
|
||||
updatedPersonalData.newPassword,
|
||||
);
|
||||
// try without @ part
|
||||
@@ -160,7 +128,7 @@ describe('User Management', () => {
|
||||
|
||||
it(`should change user email`, () => {
|
||||
personalSettingsPage.actions.loginAndVisit(
|
||||
instanceOwner.email,
|
||||
INSTANCE_OWNER.email,
|
||||
updatedPersonalData.newPassword,
|
||||
);
|
||||
personalSettingsPage.actions.updateEmail(updatedPersonalData.newEmail);
|
||||
|
||||
@@ -1,24 +1,11 @@
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { NDV, WorkflowPage as WorkflowPageClass, WorkflowsPage } from '../pages';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
const workflowPage = new WorkflowPageClass();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Execution', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -6,24 +6,14 @@ import {
|
||||
NEW_QUERY_AUTH_ACCOUNT_NAME,
|
||||
} from './../constants';
|
||||
import {
|
||||
DEFAULT_USER_EMAIL,
|
||||
DEFAULT_USER_PASSWORD,
|
||||
GMAIL_NODE_NAME,
|
||||
NEW_GOOGLE_ACCOUNT_NAME,
|
||||
NEW_TRELLO_ACCOUNT_NAME,
|
||||
SCHEDULE_TRIGGER_NODE_NAME,
|
||||
TRELLO_NODE_NAME,
|
||||
} from '../constants';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { CredentialsPage, CredentialsModal, WorkflowPage, NDV } from '../pages';
|
||||
import CustomNodeWithN8nCredentialFixture from '../fixtures/Custom_node_n8n_credential.json';
|
||||
import CustomNodeWithCustomCredentialFixture from '../fixtures/Custom_node_custom_credential.json';
|
||||
import CustomCredential from '../fixtures/Custom_credential.json';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
const credentialsPage = new CredentialsPage();
|
||||
const credentialsModal = new CredentialsModal();
|
||||
const workflowPage = new WorkflowPage();
|
||||
@@ -32,12 +22,7 @@ const nodeDetailsView = new NDV();
|
||||
const NEW_CREDENTIAL_NAME = 'Something else';
|
||||
|
||||
describe('Credentials', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
cy.visit(credentialsPage.url);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage } from '../pages';
|
||||
import { WorkflowExecutionsTab } from '../pages/workflow-executions-tab';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const executionsTab = new WorkflowExecutionsTab();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
// Test suite for executions tab
|
||||
describe('Current Workflow Executions', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
cy.createFixtureWorkflow('Test_workflow_4_executions_view.json', `My test workflow`);
|
||||
createMockExecutions();
|
||||
|
||||
@@ -4,25 +4,15 @@ import { CredentialsModal, WorkflowPage } from '../pages';
|
||||
import CustomNodeWithN8nCredentialFixture from '../fixtures/Custom_node_n8n_credential.json';
|
||||
import CustomNodeWithCustomCredentialFixture from '../fixtures/Custom_node_custom_credential.json';
|
||||
import CustomCredential from '../fixtures/Custom_credential.json';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
|
||||
const credentialsModal = new CredentialsModal();
|
||||
const nodeCreatorFeature = new NodeCreator();
|
||||
const workflowPage = new WorkflowPage();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
// We separate-out the custom nodes because they require injecting nodes and credentials
|
||||
// so the /nodes and /credentials endpoints are intercepted and non-cached.
|
||||
// We want to keep the other tests as fast as possible so we don't want to break the cache in those.
|
||||
describe('Community Nodes', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
})
|
||||
beforeEach(() => {
|
||||
cy.intercept('/types/nodes.json', { middleware: true }, (req) => {
|
||||
req.headers['cache-control'] = 'no-cache, no-store';
|
||||
@@ -43,7 +33,7 @@ describe('Community Nodes', () => {
|
||||
credentials.push(CustomCredential);
|
||||
})
|
||||
})
|
||||
cy.signin({ email, password });
|
||||
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
import { VariablesPage } from '../pages/variables';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
|
||||
const variablesPage = new VariablesPage();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Variables', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
it('should show the unlicensed action box when the feature is disabled', () => {
|
||||
cy.disableFeature('feat:variables');
|
||||
cy.signin({ email, password });
|
||||
cy.disableFeature('variables', false);
|
||||
cy.visit(variablesPage.url);
|
||||
|
||||
variablesPage.getters.unavailableResourcesList().should('be.visible');
|
||||
@@ -25,11 +13,10 @@ describe('Variables', () => {
|
||||
|
||||
describe('licensed', () => {
|
||||
before(() => {
|
||||
cy.enableFeature('feat:variables');
|
||||
cy.enableFeature('variables');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
cy.intercept('GET', '/rest/variables').as('loadVariables');
|
||||
|
||||
cy.visit(variablesPage.url);
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('NDV', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
workflowPage.actions.renameWorkflow(uuid());
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
@@ -311,6 +299,9 @@ describe('NDV', () => {
|
||||
.realHover();
|
||||
|
||||
ndv.actions.changeOutputRunSelector('1 of 2 (2 items)')
|
||||
ndv.getters.inputTableRow(1)
|
||||
.should('have.text', '8888')
|
||||
.realHover();
|
||||
ndv.getters.outputHoveringItem().should('have.text', '8888');
|
||||
// todo there's a bug here need to fix ADO-534
|
||||
// ndv.getters.outputHoveringItem().should('not.exist');
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
|
||||
const workflowPage = new WorkflowPageClass();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
function checkStickiesStyle( top: number, left: number, height: number, width: number, zIndex?: number) {
|
||||
workflowPage.getters.stickies().should(($el) => {
|
||||
expect($el).to.have.css('top', `${top}px`);
|
||||
@@ -22,12 +15,7 @@ function checkStickiesStyle( top: number, left: number, height: number, width: n
|
||||
}
|
||||
|
||||
describe('Canvas Actions', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
|
||||
cy.window().then(
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage, NDV, CredentialsModal } from '../pages';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
@@ -9,18 +7,8 @@ const credentialsModal = new CredentialsModal();
|
||||
const NO_CREDENTIALS_MESSAGE = 'Please add your credential';
|
||||
const INVALID_CREDENTIALS_MESSAGE = 'Please check your credential';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Resource Locator', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
import { NodeCreator } from '../pages/features/node-creator';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { NDV } from '../pages/ndv';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
|
||||
const nodeCreatorFeature = new NodeCreator();
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
const NDVModal = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Node Creator', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('NDV', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
workflowPage.actions.visit();
|
||||
workflowPage.actions.renameWorkflow(uuid());
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { NDV } from '../pages/ndv';
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Code node', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import {
|
||||
CODE_NODE_NAME,
|
||||
DEFAULT_USER_EMAIL,
|
||||
DEFAULT_USER_PASSWORD,
|
||||
MANUAL_TRIGGER_NODE_NAME,
|
||||
META_KEY,
|
||||
SCHEDULE_TRIGGER_NODE_NAME,
|
||||
@@ -14,20 +11,10 @@ const IMPORT_WORKFLOW_URL = 'https://gist.githubusercontent.com/OlegIvaniv/010bd
|
||||
const DUPLICATE_WORKFLOW_NAME = 'Duplicated workflow';
|
||||
const DUPLICATE_WORKFLOW_TAG = 'Duplicate';
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
|
||||
describe('Workflow Actions', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('HTTP Request node', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
beforeEach(() => {
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
it('should make a request with a URL and receive a response', () => {
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
import { randFirstName, randLastName } from '@ngneat/falso';
|
||||
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
|
||||
const email = DEFAULT_USER_EMAIL;
|
||||
const password = DEFAULT_USER_PASSWORD;
|
||||
const firstName = randFirstName();
|
||||
const lastName = randLastName();
|
||||
|
||||
describe('Expression editor modal', () => {
|
||||
before(() => {
|
||||
cy.setup({ email, firstName, lastName, password });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.signin({ email, password });
|
||||
WorkflowPage.actions.visit();
|
||||
WorkflowPage.actions.addInitialNodeToCanvas('Manual');
|
||||
WorkflowPage.actions.addNodeToCanvas('Hacker News');
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
export * from './base';
|
||||
export * from './credentials';
|
||||
export * from './signin';
|
||||
export * from './signup';
|
||||
export * from './workflows';
|
||||
export * from './workflow';
|
||||
export * from './modals';
|
||||
|
||||
@@ -26,9 +26,5 @@ export class MainSidebar extends BasePage {
|
||||
openUserMenu: () => {
|
||||
this.getters.userMenu().find('[role="button"]').last().click();
|
||||
},
|
||||
signout: () => {
|
||||
this.actions.openUserMenu();
|
||||
cy.getByTestId('workflow-menu-item-logout').click();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { BasePage } from './base';
|
||||
|
||||
export class SigninPage extends BasePage {
|
||||
url = '/signin';
|
||||
getters = {
|
||||
form: () => cy.getByTestId('auth-form'),
|
||||
email: () => cy.getByTestId('email'),
|
||||
password: () => cy.getByTestId('password'),
|
||||
submit: () => cy.get('button'),
|
||||
};
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { BasePage } from './base';
|
||||
|
||||
// todo rename to setup
|
||||
export class SignupPage extends BasePage {
|
||||
url = '/setup';
|
||||
getters = {
|
||||
form: () => cy.getByTestId('auth-form'),
|
||||
email: () => cy.getByTestId('email'),
|
||||
firstName: () => cy.getByTestId('firstName'),
|
||||
lastName: () => cy.getByTestId('lastName'),
|
||||
password: () => cy.getByTestId('password'),
|
||||
submit: () => cy.get('button'),
|
||||
skip: () => cy.get('a'),
|
||||
};
|
||||
}
|
||||
@@ -1,32 +1,6 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
import 'cypress-real-events';
|
||||
import { WorkflowsPage, SigninPage, SignupPage, SettingsUsersPage, WorkflowPage } from '../pages';
|
||||
import { N8N_AUTH_COOKIE } from '../constants';
|
||||
import { MessageBox } from '../pages/modals/message-box';
|
||||
import { WorkflowPage } from '../pages';
|
||||
import { BASE_URL, N8N_AUTH_COOKIE } from '../constants';
|
||||
|
||||
Cypress.Commands.add('getByTestId', (selector, ...args) => {
|
||||
return cy.get(`[data-test-id="${selector}"]`, ...args);
|
||||
@@ -59,136 +33,35 @@ Cypress.Commands.add('waitForLoad', (waitForIntercepts = true) => {
|
||||
// we can't set them up here because at this point it would be too late
|
||||
// and the requests would already have been made
|
||||
if (waitForIntercepts) {
|
||||
cy.wait(['@loadSettings', '@loadLogin']);
|
||||
cy.wait(['@loadSettings']);
|
||||
}
|
||||
cy.getByTestId('node-view-loader', { timeout: 20000 }).should('not.exist');
|
||||
cy.get('.el-loading-mask', { timeout: 20000 }).should('not.exist');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('signin', ({ email, password }) => {
|
||||
const signinPage = new SigninPage();
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
|
||||
cy.session(
|
||||
[email, password],
|
||||
() => {
|
||||
cy.visit(signinPage.url);
|
||||
|
||||
signinPage.getters.form().within(() => {
|
||||
signinPage.getters.email().type(email);
|
||||
signinPage.getters.password().type(password);
|
||||
signinPage.getters.submit().click();
|
||||
});
|
||||
|
||||
// we should be redirected to /workflows
|
||||
cy.url().should('include', workflowsPage.url);
|
||||
Cypress.session.clearAllSavedSessions();
|
||||
cy.session([email, password], () => cy.request('POST', '/rest/login', { email, password }), {
|
||||
validate() {
|
||||
cy.getCookie(N8N_AUTH_COOKIE).should('exist');
|
||||
},
|
||||
{
|
||||
validate() {
|
||||
cy.getCookie(N8N_AUTH_COOKIE).should('exist');
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('signout', () => {
|
||||
cy.visit('/signout');
|
||||
cy.waitForLoad();
|
||||
cy.url().should('include', '/signin');
|
||||
cy.request('POST', '/rest/logout');
|
||||
cy.getCookie(N8N_AUTH_COOKIE).should('not.exist');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('signup', ({ firstName, lastName, password, url }) => {
|
||||
const signupPage = new SignupPage();
|
||||
|
||||
cy.visit(url);
|
||||
|
||||
signupPage.getters.form().within(() => {
|
||||
cy.url().then((url) => {
|
||||
cy.intercept('/rest/users/*').as('userSignup')
|
||||
signupPage.getters.firstName().type(firstName);
|
||||
signupPage.getters.lastName().type(lastName);
|
||||
signupPage.getters.password().type(password);
|
||||
signupPage.getters.submit().click();
|
||||
cy.wait('@userSignup');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('setup', ({ email, firstName, lastName, password }, skipIntercept = false) => {
|
||||
const signupPage = new SignupPage();
|
||||
|
||||
cy.intercept('GET', signupPage.url).as('setupPage');
|
||||
cy.visit(signupPage.url);
|
||||
cy.wait('@setupPage');
|
||||
|
||||
signupPage.getters.form().within(() => {
|
||||
cy.url().then((url) => {
|
||||
if (url.includes(signupPage.url)) {
|
||||
signupPage.getters.email().type(email);
|
||||
signupPage.getters.firstName().type(firstName);
|
||||
signupPage.getters.lastName().type(lastName);
|
||||
signupPage.getters.password().type(password);
|
||||
|
||||
cy.intercept('POST', '/rest/owner/setup').as('setupRequest');
|
||||
signupPage.getters.submit().click();
|
||||
|
||||
if(!skipIntercept) {
|
||||
cy.wait('@setupRequest');
|
||||
}
|
||||
} else {
|
||||
cy.log('User already signed up');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('interceptREST', (method, url) => {
|
||||
cy.intercept(method, `http://localhost:5678/rest${url}`);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('inviteUsers', ({ instanceOwner, users }) => {
|
||||
const settingsUsersPage = new SettingsUsersPage();
|
||||
const setFeature = (feature: string, enabled: boolean) =>
|
||||
cy.request('PATCH', `${BASE_URL}/rest/e2e/feature`, { feature: `feat:${feature}`, enabled });
|
||||
|
||||
cy.signin(instanceOwner);
|
||||
|
||||
users.forEach((user) => {
|
||||
cy.signin(instanceOwner);
|
||||
cy.visit(settingsUsersPage.url);
|
||||
|
||||
cy.interceptREST('POST', '/users').as('inviteUser');
|
||||
|
||||
settingsUsersPage.getters.inviteButton().click();
|
||||
settingsUsersPage.getters.inviteUsersModal().within((modal) => {
|
||||
settingsUsersPage.getters.inviteUsersModalEmailsInput().type(user.email).type('{enter}');
|
||||
});
|
||||
|
||||
cy.wait('@inviteUser').then((interception) => {
|
||||
const inviteLink = interception.response!.body.data[0].user.inviteAcceptUrl;
|
||||
cy.log(JSON.stringify(interception.response!.body.data[0].user));
|
||||
cy.log(inviteLink);
|
||||
cy.signout();
|
||||
cy.signup({ ...user, url: inviteLink });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('resetAll', () => {
|
||||
cy.task('reset');
|
||||
Cypress.session.clearAllSavedSessions();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('setupOwner', (payload) => {
|
||||
cy.task('setup-owner', payload);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('enableFeature', (feature) => {
|
||||
cy.task('set-feature', { feature, enabled: true });
|
||||
});
|
||||
|
||||
Cypress.Commands.add('disableFeature', (feature) => {
|
||||
cy.task('set-feature', { feature, enabled: false });
|
||||
});
|
||||
Cypress.Commands.add('enableFeature', (feature: string) => setFeature(feature, true));
|
||||
Cypress.Commands.add('disableFeature', (feature): string => setFeature(feature, false));
|
||||
|
||||
Cypress.Commands.add('grantBrowserPermissions', (...permissions: string[]) => {
|
||||
if (Cypress.isBrowser('chrome')) {
|
||||
|
||||
@@ -1,28 +1,19 @@
|
||||
// ***********************************************************
|
||||
// This example support/e2e.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
import { BASE_URL, INSTANCE_MEMBERS, INSTANCE_OWNER } from '../constants';
|
||||
import './commands';
|
||||
|
||||
before(() => {
|
||||
cy.resetAll();
|
||||
cy.request('POST', `${BASE_URL}/rest/e2e/reset`, {
|
||||
owner: INSTANCE_OWNER,
|
||||
members: INSTANCE_MEMBERS,
|
||||
});
|
||||
});
|
||||
|
||||
// Load custom nodes and credentials fixtures
|
||||
beforeEach(() => {
|
||||
if (!cy.config('disableAutoLogin')) {
|
||||
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||
}
|
||||
|
||||
cy.intercept('GET', '/rest/settings').as('loadSettings');
|
||||
cy.intercept('GET', '/rest/login').as('loadLogin');
|
||||
|
||||
// Always intercept the request to test credentials and return a success
|
||||
cy.intercept('POST', '/rest/credentials/test', {
|
||||
|
||||
@@ -8,25 +8,14 @@ interface SigninPayload {
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface SetupPayload {
|
||||
email: string;
|
||||
password: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
interface SignupPayload extends SetupPayload {
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface InviteUsersPayload {
|
||||
instanceOwner: SigninPayload;
|
||||
users: SetupPayload[];
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface SuiteConfigOverrides {
|
||||
disableAutoLogin: boolean;
|
||||
}
|
||||
|
||||
interface Chainable {
|
||||
config(key: keyof SuiteConfigOverrides): boolean;
|
||||
getByTestId(
|
||||
selector: string,
|
||||
...args: (Partial<Loggable & Timeoutable & Withinable & Shadow> | undefined)[]
|
||||
@@ -35,12 +24,7 @@ declare global {
|
||||
createFixtureWorkflow(fixtureKey: string, workflowName: string): void;
|
||||
signin(payload: SigninPayload): void;
|
||||
signout(): void;
|
||||
signup(payload: SignupPayload): void;
|
||||
setup(payload: SetupPayload, skipIntercept?: boolean): void;
|
||||
setupOwner(payload: SetupPayload): void;
|
||||
inviteUsers(payload: InviteUsersPayload): void;
|
||||
interceptREST(method: string, url: string): Chainable<Interception>;
|
||||
resetAll(): void;
|
||||
enableFeature(feature: string): void;
|
||||
disableFeature(feature: string): void;
|
||||
waitForLoad(waitForIntercepts?: boolean): void;
|
||||
|
||||
Reference in New Issue
Block a user