Skip to content

Commit

Permalink
Merge branch 'master' into feature/resource-mapping-component
Browse files Browse the repository at this point in the history
* master:
  fix(core): Serialize dates and regexps when reading from augmented objects (#6086)
  feat(editor): Enhance Node Creator actions view (#5954)
  fix(editor): Make the frontend work again when `NODE_FUNCTION_ALLOW_EXTERNAL` is set (no-changelog) (#6058)
  feat(editor): Add SQL editor support (#5517)
  refactor(editor): Track advanced filter custom data usage (#6084)
  refactor(editor): Replace monaco-editor/prismjs with CodeMirror (#5983)
  ci: Enforce no unused imports (no-changelog) (#6073)

# Conflicts:
#	packages/editor-ui/src/components/ParameterInput.vue
#	packages/editor-ui/src/stores/nodeTypes.ts
  • Loading branch information
MiloradFilipovic committed Apr 26, 2023
2 parents d30dbaf + a4eb46a commit 0b823c7
Show file tree
Hide file tree
Showing 142 changed files with 3,993 additions and 3,197 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/11-inline-expression-editor.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ describe('Inline expression editor', () => {
WorkflowPage.getters.inlineExpressionEditorInput().clear();
WorkflowPage.getters.inlineExpressionEditorInput().type('{{');
WorkflowPage.getters.inlineExpressionEditorInput().type('$parameter["operation"]');
WorkflowPage.getters.inlineExpressionEditorOutput().contains(/^getAll$/);
WorkflowPage.getters.inlineExpressionEditorOutput().contains(/^get$/);
});
});
4 changes: 2 additions & 2 deletions cypress/e2e/13-pinning.cy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
HTTP_REQUEST_NODE_NAME,
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
MANUAL_TRIGGER_NODE_NAME,
PIPEDRIVE_NODE_NAME,
SET_NODE_NAME,
} from '../constants';
Expand Down Expand Up @@ -75,7 +75,7 @@ describe('Data pinning', () => {
});

it('Should be able to reference paired items in a node located before pinned data', () => {
workflowPage.actions.addInitialNodeToCanvas(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
workflowPage.actions.addInitialNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
workflowPage.actions.addNodeToCanvas(HTTP_REQUEST_NODE_NAME, true, true);
ndv.actions.setPinnedData([{ http: 123 }]);
ndv.actions.close();
Expand Down
109 changes: 105 additions & 4 deletions cypress/e2e/4-node-creator.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.getCreatorItem('On app event').click();

nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image');
nodeCreatorFeature.getters.getCreatorItem('Results in other categories (1)').should('exist');
nodeCreatorFeature.getters.creatorItem().should('have.length', 2);
nodeCreatorFeature.getters.getCategoryItem('Results in other categories').should('exist');
nodeCreatorFeature.getters.creatorItem().should('have.length', 1);
nodeCreatorFeature.getters.getCreatorItem('Edit Image').should('exist');
nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image123123');
nodeCreatorFeature.getters.creatorItem().should('have.length', 0);
Expand Down Expand Up @@ -101,7 +101,7 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.activeSubcategory().should('have.text', 'FTP');
nodeCreatorFeature.getters.searchBar().find('input').clear().type('file');
// Navigate to rename action which should be the 4th item
nodeCreatorFeature.getters.searchBar().find('input').type('{downarrow} {downarrow} {downarrow} {rightarrow}');
nodeCreatorFeature.getters.searchBar().find('input').type('{uparrow}{uparrow}{rightarrow}');
NDVModal.getters.parameterInput('operation').should('contain.text', 'Rename');
})

Expand All @@ -127,9 +127,107 @@ describe('Node Creator', () => {
})
nodeCreatorFeature.getters.searchBar().find('input').clear().type(doubleActionNode);
nodeCreatorFeature.getters.getCreatorItem(doubleActionNode).click();
nodeCreatorFeature.getters.creatorItem().should('have.length', 2);
nodeCreatorFeature.getters.creatorItem().should('have.length', 4);
})

it('should have "Actions" section collapsed when opening actions view from Trigger root view', () => {
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('ActiveCampaign');
nodeCreatorFeature.getters.getCreatorItem('ActiveCampaign').click();
nodeCreatorFeature.getters.getCategoryItem('Actions').should('exist');
nodeCreatorFeature.getters.getCategoryItem('Triggers').should('exist');

nodeCreatorFeature.getters.getCategoryItem('Triggers').parent().should('not.have.attr', 'data-category-collapsed');
nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('have.attr', 'data-category-collapsed', 'true');
nodeCreatorFeature.getters.getCategoryItem('Actions').click()
nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('not.have.attr', 'data-category-collapsed');
});

it('should have "Triggers" section collapsed when opening actions view from Regular root view', () => {
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.getCreatorItem('Manually').click();

nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
nodeCreatorFeature.getters.getCreatorItem('n8n').click();

nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('not.have.attr', 'data-category-collapsed');
nodeCreatorFeature.getters.getCategoryItem('Actions').click()
nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('have.attr', 'data-category-collapsed');
nodeCreatorFeature.getters.getCategoryItem('Triggers').parent().should('have.attr', 'data-category-collapsed');
nodeCreatorFeature.getters.getCategoryItem('Triggers').click()
nodeCreatorFeature.getters.getCategoryItem('Triggers').parent().should('not.have.attr', 'data-category-collapsed');
});

it('should show callout and two suggested nodes if node has no trigger actions', () => {
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();

cy.getByTestId('actions-panel-no-triggers-callout').should('be.visible');
nodeCreatorFeature.getters.getCreatorItem('On a Schedule').should('be.visible');
nodeCreatorFeature.getters.getCreatorItem('On a Webhook call').should('be.visible');
});

it('should show intro callout if user has not made a production execution', () => {
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();

cy.getByTestId('actions-panel-activation-callout').should('be.visible');
nodeCreatorFeature.getters.activeSubcategory().find('button').click();
nodeCreatorFeature.getters.searchBar().find('input').clear()

nodeCreatorFeature.getters.getCreatorItem('On a schedule').click();

// Setup 1s interval execution
cy.getByTestId('parameter-input-field').click();
cy.getByTestId('parameter-input-field')
.find('.el-select-dropdown')
.find('.option-headline')
.contains('Seconds')
.click();
cy.getByTestId('parameter-input-secondsInterval').clear().type('1');

NDVModal.actions.close();

nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();
nodeCreatorFeature.getters.getCreatorItem('Get All People').click();
NDVModal.actions.close();

WorkflowPage.actions.saveWorkflowOnButtonClick();
WorkflowPage.actions.activateWorkflow();
WorkflowPage.getters.activatorSwitch().should('have.class', 'is-checked');

// Wait for schedule 1s execution to mark user as having made a production execution
cy.wait(1500);
cy.reload()

// Action callout should not be visible after user has made a production execution
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();

cy.getByTestId('actions-panel-activation-callout').should('not.exist');
});

it('should show Trigger and Actions sections during search', () => {
nodeCreatorFeature.actions.openNodeCreator();

nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();

nodeCreatorFeature.getters.searchBar().find('input').clear().type('Non existent action name');

nodeCreatorFeature.getters.getCategoryItem('Triggers').should('be.visible');
nodeCreatorFeature.getters.getCategoryItem('Actions').should('be.visible');
cy.getByTestId('actions-panel-no-triggers-callout').should('be.visible');
nodeCreatorFeature.getters.getCreatorItem('On a Schedule').should('be.visible');
nodeCreatorFeature.getters.getCreatorItem('On a Webhook call').should('be.visible');
});

describe('should correctly append manual trigger for regular actions', () => {
// For these sources, manual node should be added
const sourcesWithAppend = [
Expand All @@ -152,6 +250,7 @@ describe('Node Creator', () => {
source.handler()
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
nodeCreatorFeature.getters.getCreatorItem('n8n').click();
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
nodeCreatorFeature.getters.getCreatorItem('Create a credential').click();
NDVModal.actions.close();
WorkflowPage.getters.canvasNodes().should('have.length', 2);
Expand All @@ -162,12 +261,14 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.canvasAddButton().click();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
nodeCreatorFeature.getters.getCreatorItem('n8n').click();
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
nodeCreatorFeature.getters.getCreatorItem('Create a credential').click();
NDVModal.actions.close();
WorkflowPage.actions.deleteNode('When clicking "Execute Workflow"')
WorkflowPage.getters.canvasNodePlusEndpointByName('n8n').click()
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
nodeCreatorFeature.getters.getCreatorItem('n8n').click();
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
nodeCreatorFeature.getters.getCreatorItem('Create a credential').click();
NDVModal.actions.close();
WorkflowPage.getters.canvasNodes().should('have.length', 2);
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/9-expression-editor-modal.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ describe('Expression editor modal', () => {
it('should resolve $parameter[]', () => {
WorkflowPage.getters.expressionModalInput().clear();
WorkflowPage.getters.expressionModalInput().type('{{ $parameter["operation"]');
WorkflowPage.getters.expressionModalOutput().contains(/^getAll$/);
WorkflowPage.getters.expressionModalOutput().contains(/^get$/);
});
});
6 changes: 4 additions & 2 deletions cypress/pages/features/node-creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export class NodeCreator extends BasePage {
plusButton: () => cy.getByTestId('node-creator-plus-button'),
canvasAddButton: () => cy.getByTestId('canvas-add-button'),
searchBar: () => cy.getByTestId('search-bar'),
getCategoryItem: (label: string) => cy.get(`[data-keyboard-nav-id="${label}"]`),
getCreatorItem: (label: string) =>
this.getters.creatorItem().contains(label).parents('[data-test-id="item-iterator-item"]'),
getNthCreatorItem: (n: number) => this.getters.creatorItem().eq(n),
Expand All @@ -15,10 +16,11 @@ export class NodeCreator extends BasePage {
selectedTab: () => this.getters.nodeCreatorTabs().find('.is-active'),
categorizedItems: () => cy.getByTestId('categorized-items'),
creatorItem: () => cy.getByTestId('item-iterator-item'),
categoryItem: () => cy.getByTestId('node-creator-category-item'),
communityNodeTooltip: () => cy.getByTestId('node-item-community-tooltip'),
noResults: () => cy.getByTestId('categorized-no-results'),
noResults: () => cy.getByTestId('node-creator-no-results'),
nodeItemName: () => cy.getByTestId('node-creator-item-name'),
activeSubcategory: () => cy.getByTestId('categorized-items-subcategory'),
activeSubcategory: () => cy.getByTestId('nodes-list-header'),
expandedCategories: () =>
this.getters.creatorItem().find('>div').filter('.active').invoke('text'),
};
Expand Down
5 changes: 2 additions & 3 deletions cypress/pages/ndv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class NDV extends BasePage {
outputDisplayMode: () => this.getters.outputPanel().findChildByTestId('ndv-run-data-display-mode').first(),
pinDataButton: () => cy.getByTestId('ndv-pin-data'),
editPinnedDataButton: () => cy.getByTestId('ndv-edit-pinned-data'),
pinnedDataEditor: () => this.getters.outputPanel().find('.monaco-editor[role=code]'),
pinnedDataEditor: () => this.getters.outputPanel().find('.cm-editor .cm-scroller'),
runDataPaneHeader: () => cy.getByTestId('run-data-pane-header'),
savePinnedDataButton: () => this.getters.runDataPaneHeader().find('button').filter(':visible').contains('Save'),
outputTableRows: () => this.getters.outputDataContainer().find('table tr'),
Expand Down Expand Up @@ -77,8 +77,7 @@ export class NDV extends BasePage {
this.getters.editPinnedDataButton().click();

this.getters.pinnedDataEditor().click();
this.getters.pinnedDataEditor().type(`{selectall}{backspace}`);
this.getters.pinnedDataEditor().type(JSON.stringify(data).replace(new RegExp('{', 'g'), '{{}'));
this.getters.pinnedDataEditor().type(`{selectall}{backspace}${JSON.stringify(data).replace(new RegExp('{', 'g'), '{{}')}`);

this.actions.savePinnedData();
},
Expand Down
3 changes: 2 additions & 1 deletion cypress/pages/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ export class WorkflowPage extends BasePage {
if(action) {
cy.contains(action).click()
} else {
cy.getByTestId('item-iterator-item').eq(1).click()
// Select the first action
cy.get('[data-keyboard-nav-type="action"]').eq(0).click()
}
}
})
Expand Down
12 changes: 12 additions & 0 deletions packages/@n8n_io/eslint-config/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const config = (module.exports = {
*/
'eslint-plugin-n8n-local-rules',

/** https://github.com/sweepline/eslint-plugin-unused-imports */
'unused-imports',

/** https://github.com/sindresorhus/eslint-plugin-unicorn */
'eslint-plugin-unicorn',
],
Expand Down Expand Up @@ -426,6 +429,15 @@ const config = (module.exports = {
*/
'import/prefer-default-export': 'off',

// ----------------------------------
// no-unused-imports
// ----------------------------------

/**
* https://github.com/sweepline/eslint-plugin-unused-imports/blob/master/docs/rules/no-unused-imports.md
*/
'unused-imports/no-unused-imports': process.env.NODE_ENV === 'development' ? 'warn' : 'error',

/** https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-unnecessary-await.md */
'unicorn/no-unnecessary-await': 'error',

Expand Down
1 change: 1 addition & 0 deletions packages/@n8n_io/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"eslint-plugin-n8n-local-rules": "~1.0",
"eslint-plugin-prettier": "~4.2",
"eslint-plugin-unicorn": "~46.0",
"eslint-plugin-unused-imports": "~2.0",
"eslint-plugin-vue": "~7.17"
},
"scripts": {
Expand Down
2 changes: 0 additions & 2 deletions packages/cli/src/UserManagement/UserManagementHelper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { In } from 'typeorm';
import type express from 'express';
import { compare, genSaltSync, hash } from 'bcryptjs';
import { Container } from 'typedi';

Expand All @@ -12,7 +11,6 @@ import type { User } from '@db/entities/User';
import { MAX_PASSWORD_LENGTH, MIN_PASSWORD_LENGTH } from '@db/entities/User';
import type { Role } from '@db/entities/Role';
import { RoleRepository } from '@db/repositories';
import type { AuthenticatedRequest } from '@/requests';
import config from '@/config';
import { getWebhookBaseUrl } from '@/WebhookHelpers';
import { License } from '@/License';
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/WorkflowRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import type {
IRun,
WorkflowExecuteMode,
WorkflowHooks,
WorkflowSettings,
} from 'n8n-workflow';
import {
ErrorReporterProxy as ErrorReporter,
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ if (inE2ETests) {
N8N_PUBLIC_API_DISABLED: 'true',
EXTERNAL_FRONTEND_HOOKS_URLS: '',
N8N_PERSONALIZATION_ENABLED: 'false',
NODE_FUNCTION_ALLOW_EXTERNAL: 'node-fetch',
};
} else if (inTest) {
process.env.N8N_PUBLIC_API_DISABLED = 'true';
Expand Down
24 changes: 20 additions & 4 deletions packages/design-system/src/components/N8nCallout/Callout.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div :class="classes" role="alert">
<div :class="$style['message-section']">
<div :class="$style.icon">
<div :class="$style.messageSection">
<div :class="$style.icon" v-if="!iconless">
<n8n-icon :icon="getIcon" :size="theme === 'secondary' ? 'medium' : 'large'" />
</div>
<n8n-text size="small">
Expand Down Expand Up @@ -44,10 +44,21 @@ export default defineComponent({
type: String,
default: 'info-circle',
},
iconless: {
type: Boolean,
},
slim: {
type: Boolean,
},
},
computed: {
classes(): string[] {
return ['n8n-callout', this.$style.callout, this.$style[this.theme]];
return [
'n8n-callout',
this.$style.callout,
this.$style[this.theme],
this.slim ? this.$style.slim : '',
];
},
getIcon(): string {
if (Object.keys(CALLOUT_DEFAULT_ICONS).includes(this.theme)) {
Expand All @@ -70,9 +81,14 @@ export default defineComponent({
border-radius: var(--border-radius-base);
align-items: center;
line-height: var(--font-line-height-loose);
&.slim {
line-height: var(--font-line-height-loose);
padding: var(--spacing-3xs) var(--spacing-2xs);
}
}
.message-section {
.messageSection {
display: flex;
align-items: center;
}
Expand Down
Loading

0 comments on commit 0b823c7

Please sign in to comment.