Skip to content

Commit

Permalink
Merge branch 'master' into ado-258-date-extensions-updates
Browse files Browse the repository at this point in the history
* master:
  refactor(core): Luxon dependency update (#5301)
  feat(Notion Node): Add image block (#5237)
  fix(Set Node): Fix behaviour when selecting continueOnFail & PairedItem (#5257)
  feat(editor): Continue to show mapping tooltip after dismiss (#5289)
  refactor(editor): Upgrade to jsPlumb 5 (#4989)
  feat(core): Export OpenAPI spec for external tools (#5294)
  refactor: Clean up workflow stats test file (#5282)
  docs(Postgres Node): Remove overkill notice for postgres & paireditem (#5291)
  fix(n8n Trigger Node): Use the new icon for N8N Trigger node (no-changelog) (#5290)
  fix(editor): Add SMTP info translation link slot (#5288)
  refactor(core): Load and validate all config at startup (no-changelog) (#5283)
  feat: Add multiple workflows text search filtering E2E test scenarios (no-changelog) (#5276)
  ci: Re-enable CI jobs on nodejs 14.x (no-changelog) (#5153)
  ci(editor): Update RunDataSchema test (no-changelog) (#5287)
  feat(editor): Add mapping support for data paths (#5191)
  test: Add unit testing to nodes (no-changelog) (#4890)
  ci(core): Fix docker nightly/custom image build (no-changelog) (#5284)
  • Loading branch information
MiloradFilipovic committed Jan 31, 2023
2 parents cdd8911 + 1d85e23 commit 0d84023
Show file tree
Hide file tree
Showing 85 changed files with 3,122 additions and 2,587 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

strategy:
matrix:
node-version: [16.x]
node-version: [14.x, 16.x]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-pull-requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:

strategy:
matrix:
node-version: [16.x]
node-version: [14.x, 16.x]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:

strategy:
matrix:
node-version: [16.x]
node-version: [14.x, 16.x]

steps:
- name: Call Start URL - optionally
Expand Down
34 changes: 22 additions & 12 deletions cypress/e2e/1-workflows.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const lastName = randLastName();
const WorkflowsPage = new WorkflowsPageClass();
const WorkflowPage = new WorkflowPageClass();

const multipleWorkflowsCount = 5;

describe('Workflows', () => {
before(() => {
cy.resetAll();
Expand Down Expand Up @@ -38,39 +40,47 @@ describe('Workflows', () => {
WorkflowPage.getters.workflowTags().should('contain.text', 'some-tag-2');
});

it('should create a new workflow using add workflow button', () => {
it('should create multiple new workflows using add workflow button', () => {
WorkflowsPage.getters.newWorkflowButtonCard().should('not.exist');
WorkflowsPage.getters.createWorkflowButton().click();

cy.createFixtureWorkflow('Test_workflow_2.json', `Add Workflow Button Workflow ${uuid()}`);
[...Array(multipleWorkflowsCount).keys()].forEach(() => {
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.createWorkflowButton().click();

cy.createFixtureWorkflow('Test_workflow_2.json', `My New Workflow ${uuid()}`);

WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-1');
WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-2');
WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-1');
WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-2');
});
});

it('should search for a workflow', () => {
// One Result
WorkflowsPage.getters.searchBar().type('Empty State Card Workflow');

WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters
.workflowCard('Empty State Card Workflow')
.should('contain.text', 'Empty State Card Workflow');

WorkflowsPage.getters.searchBar().clear().type('Add Workflow Button Workflow');
// Multiple Results
WorkflowsPage.getters.searchBar().clear().type('My New Workflow');
WorkflowsPage.getters.workflowCards().should('have.length', multipleWorkflowsCount);
WorkflowsPage.getters.workflowCard('My New Workflow').should('contain.text', 'My New Workflow');

WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters
.workflowCard('Add Workflow Button Workflow')
.should('contain.text', 'Add Workflow Button Workflow');
// All Results
WorkflowsPage.getters.searchBar().clear().type('Workflow');
WorkflowsPage.getters.workflowCards().should('have.length', multipleWorkflowsCount + 1);
WorkflowsPage.getters.workflowCard('Workflow').should('contain.text', 'Workflow');

// No Results
WorkflowsPage.getters.searchBar().clear().type('Some non-existent workflow');
WorkflowsPage.getters.workflowCards().should('not.exist');

cy.contains('No workflows found').should('be.visible');
});

it('should delete all the workflows', () => {
WorkflowsPage.getters.workflowCards().should('have.length', 2);
WorkflowsPage.getters.workflowCards().should('have.length', multipleWorkflowsCount + 1);

WorkflowsPage.getters.workflowCards().each(($el) => {
const workflowName = $el.find('[data-test-id="workflow-card-name"]').text();
Expand Down
12 changes: 5 additions & 7 deletions cypress/e2e/10-undo-redo.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@ describe('Undo/Redo', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(SET_NODE_NAME);
WorkflowPage.getters.nodeConnections().first().trigger('mouseover', { force: true });
cy.get('.connection-actions .add').invoke('show');
cy.get('.connection-actions .add').should('be.visible');
cy.get('.connection-actions .add').click();
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.nodeConnections().realHover();
cy.get('.connection-actions .add').filter(':visible').click();
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME, false);
WorkflowPage.actions.zoomToFit();
WorkflowPage.actions.hitUndo();
WorkflowPage.getters.canvasNodes().should('have.have.length', 3);
Expand Down Expand Up @@ -141,8 +139,8 @@ describe('Undo/Redo', () => {
it('should undo/redo deleting a connection by pressing delete button', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.nodeConnections().first().trigger('mouseover', { force: true });
cy.get('.connection-actions .delete').click();
WorkflowPage.getters.nodeConnections().realHover();
cy.get('.connection-actions .delete').filter(':visible').should('be.visible').click();
WorkflowPage.getters.nodeConnections().should('have.length', 0);
WorkflowPage.actions.hitUndo();
WorkflowPage.getters.nodeConnections().should('have.length', 1);
Expand Down
12 changes: 5 additions & 7 deletions cypress/e2e/12-canvas.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,9 @@ describe('Canvas Actions', () => {
it('should add note between two connected nodes', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.nodeConnections().first().trigger('mouseover', { force: true });
cy.get('.connection-actions .add').as('AddNodeConnectionButton');
cy.get('@AddNodeConnectionButton').invoke('show');
cy.get('@AddNodeConnectionButton').should('be.visible').click();
WorkflowPage.actions.addNodeToCanvas(SET_NODE_NAME);
WorkflowPage.getters.nodeConnections().first().realHover();
cy.get('.connection-actions .add').filter(':visible').should('be.visible').click()
WorkflowPage.actions.addNodeToCanvas(SET_NODE_NAME, false);
WorkflowPage.getters.canvasNodes().should('have.length', 3);
WorkflowPage.getters.nodeConnections().should('have.length', 2);
// And last node should be pushed to the right
Expand Down Expand Up @@ -219,8 +217,8 @@ describe('Canvas Actions', () => {
it('should delete connections by pressing the delete button', () => {
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.nodeConnections().first().trigger('mouseover', { force: true });
cy.get('.connection-actions .delete').click();
WorkflowPage.getters.nodeConnections().first().realHover();
cy.get('.connection-actions .delete').filter(':visible').should('be.visible').click();
WorkflowPage.getters.nodeConnections().should('have.length', 0);
});

Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/2-credentials.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe('Credentials', () => {
it('should correctly render required and optional credentials', () => {
workflowPage.actions.visit();
cy.waitForLoad();
workflowPage.actions.addNodeToCanvas(PIPEDRIVE_NODE_NAME, true);
workflowPage.actions.addNodeToCanvas(PIPEDRIVE_NODE_NAME, true, true);
cy.get('body').type('{downArrow}');
cy.get('body').type('{enter}');
// Select incoming authentication
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/5-ndv.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('NDV', () => {
});

it('should show correct validation state for resource locator params', () => {
workflowPage.actions.addNodeToCanvas('Typeform', true);
workflowPage.actions.addNodeToCanvas('Typeform', true, false);
ndv.getters.container().should('be.visible');
cy.get('.has-issues').should('have.length', 0);
cy.get('[class*=hasIssues]').should('have.length', 0);
Expand All @@ -66,7 +66,7 @@ describe('NDV', () => {

it('should show validation errors only after blur or re-opening of NDV', () => {
workflowPage.actions.addNodeToCanvas('Manual Trigger');
workflowPage.actions.addNodeToCanvas('Airtable', true);
workflowPage.actions.addNodeToCanvas('Airtable', true, true);
ndv.getters.container().should('be.visible');
cy.get('.has-issues').should('have.length', 0);
ndv.getters.parameterInput('table').find('input').eq(1).focus().blur();
Expand Down
7 changes: 5 additions & 2 deletions cypress/pages/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,11 @@ export class WorkflowPage extends BasePage {
this.getters.nodeCreatorSearchBar().type('{enter}');
cy.get('body').type('{esc}');
},
addNodeToCanvas: (nodeDisplayName: string, preventNdvClose?: boolean) => {
this.getters.nodeCreatorPlusButton().click();
addNodeToCanvas: (nodeDisplayName: string, plusButtonClick = true, preventNdvClose?: boolean) => {
if (plusButtonClick) {
this.getters.nodeCreatorPlusButton().click();
}

this.getters.nodeCreatorSearchBar().type(nodeDisplayName);
this.getters.nodeCreatorSearchBar().type('{enter}');

Expand Down
2 changes: 1 addition & 1 deletion cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })

import "cypress-real-events";
import { WorkflowsPage, SigninPage, SignupPage } from '../pages';
import { N8N_AUTH_COOKIE } from '../constants';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
Expand Down
2 changes: 2 additions & 0 deletions docker/images/n8n-custom/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ FROM n8nio/base:${NODE_VERSION} as builder
COPY turbo.json package.json .npmrc pnpm-lock.yaml pnpm-workspace.yaml tsconfig.json ./
COPY scripts ./scripts
COPY packages ./packages
COPY patches ./patches

RUN apk add --update libc6-compat jq
RUN corepack enable && corepack prepare --activate
Expand All @@ -15,6 +16,7 @@ USER node
RUN pnpm install --frozen-lockfile
RUN pnpm build
RUN rm -rf node_modules
RUN jq 'del(.pnpm.patchedDependencies)' package.json > package.json.tmp; mv package.json.tmp package.json
RUN jq '{name: .name, version: .version}' packages/editor-ui/package.json > editor-ui.tmp; mv editor-ui.tmp packages/editor-ui/package.json
RUN jq '{name: .name, version: .version}' packages/design-system/package.json > design-system.tmp; mv design-system.tmp packages/design-system/package.json
RUN NODE_ENV=production pnpm install --prod --no-optional
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@types/node": "^16.11.22",
"cross-env": "^7.0.3",
"cypress": "^10.0.3",
"cypress-real-events": "^1.7.6",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"jest-mock": "^29.3.1",
Expand Down
9 changes: 3 additions & 6 deletions packages/cli/src/CredentialsOverwrites.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import config from '@/config';
import type { ICredentialDataDecryptedObject, ICredentialTypes } from 'n8n-workflow';
import { deepCopy, LoggerProxy as Logger, jsonParse } from 'n8n-workflow';
import type { ICredentialsOverwrite } from '@/Interfaces';
import * as GenericHelpers from '@/GenericHelpers';

class CredentialsOverwritesClass {
private overwriteData: ICredentialsOverwrite = {};

private resolvedTypes: string[] = [];

constructor(private credentialTypes: ICredentialTypes) {}

async init() {
const data = (await GenericHelpers.getConfigValue('credentials.overwrite.data')) as string;

constructor(private credentialTypes: ICredentialTypes) {
const data = config.getEnv('credentials.overwrite.data');
const overwriteData = jsonParse<ICredentialsOverwrite>(data, {
errorMessage: 'The credentials-overwrite is not valid JSON.',
});
Expand Down
35 changes: 12 additions & 23 deletions packages/cli/src/Db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {
import { DataSource as Connection } from 'typeorm';
import type { TlsOptions } from 'tls';
import type { DatabaseType, IDatabaseCollections } from '@/Interfaces';
import * as GenericHelpers from '@/GenericHelpers';

import config from '@/config';

Expand Down Expand Up @@ -44,17 +43,13 @@ export function linkRepository<Entity extends ObjectLiteral>(
return connection.getRepository(entityClass);
}

export async function getConnectionOptions(dbType: DatabaseType): Promise<ConnectionOptions> {
export function getConnectionOptions(dbType: DatabaseType): ConnectionOptions {
switch (dbType) {
case 'postgresdb':
const sslCa = (await GenericHelpers.getConfigValue('database.postgresdb.ssl.ca')) as string;
const sslCert = (await GenericHelpers.getConfigValue(
'database.postgresdb.ssl.cert',
)) as string;
const sslKey = (await GenericHelpers.getConfigValue('database.postgresdb.ssl.key')) as string;
const sslRejectUnauthorized = (await GenericHelpers.getConfigValue(
'database.postgresdb.ssl.rejectUnauthorized',
)) as boolean;
const sslCa = config.getEnv('database.postgresdb.ssl.ca');
const sslCert = config.getEnv('database.postgresdb.ssl.cert');
const sslKey = config.getEnv('database.postgresdb.ssl.key');
const sslRejectUnauthorized = config.getEnv('database.postgresdb.ssl.rejectUnauthorized');

let ssl: TlsOptions | undefined;
if (sslCa !== '' || sslCert !== '' || sslKey !== '' || !sslRejectUnauthorized) {
Expand All @@ -68,15 +63,15 @@ export async function getConnectionOptions(dbType: DatabaseType): Promise<Connec

return {
...getPostgresConnectionOptions(),
...(await getOptionOverrides('postgresdb')),
...getOptionOverrides('postgresdb'),
ssl,
};

case 'mariadb':
case 'mysqldb':
return {
...(dbType === 'mysqldb' ? getMysqlConnectionOptions() : getMariaDBConnectionOptions()),
...(await getOptionOverrides('mysqldb')),
...getOptionOverrides('mysqldb'),
timezone: 'Z', // set UTC as default
};

Expand All @@ -93,17 +88,13 @@ export async function init(
): Promise<IDatabaseCollections> {
if (isInitialized) return collections;

const dbType = (await GenericHelpers.getConfigValue('database.type')) as DatabaseType;
const connectionOptions = testConnectionOptions ?? (await getConnectionOptions(dbType));
const dbType = config.getEnv('database.type');
const connectionOptions = testConnectionOptions ?? getConnectionOptions(dbType);

let loggingOption: LoggerOptions = (await GenericHelpers.getConfigValue(
'database.logging.enabled',
)) as boolean;
let loggingOption: LoggerOptions = config.getEnv('database.logging.enabled');

if (loggingOption) {
const optionsString = (
(await GenericHelpers.getConfigValue('database.logging.options')) as string
).replace(/\s+/g, '');
const optionsString = config.getEnv('database.logging.options').replace(/\s+/g, '');

if (optionsString === 'all') {
loggingOption = optionsString;
Expand All @@ -112,9 +103,7 @@ export async function init(
}
}

const maxQueryExecutionTime = (await GenericHelpers.getConfigValue(
'database.logging.maxQueryExecutionTime',
)) as string;
const maxQueryExecutionTime = config.getEnv('database.logging.maxQueryExecutionTime');

Object.assign(connectionOptions, {
entities: Object.values(entities),
Expand Down
Loading

0 comments on commit 0d84023

Please sign in to comment.