mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Prevent updating node parameter value if it hasn't changed (#9535)
This commit is contained in:
parent
f914c97d11
commit
63990f14e3
|
@ -1,71 +0,0 @@
|
|||
import { WorkflowPage, NDV } from '../pages';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
describe('SQL editors', () => {
|
||||
beforeEach(() => {
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
it('should preserve changes when opening-closing Postgres node', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Postgres', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
ndv.getters
|
||||
.sqlEditorContainer()
|
||||
.click()
|
||||
.find('.cm-content')
|
||||
.type('SELECT * FROM `testTable`')
|
||||
.type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.openNode('Postgres');
|
||||
ndv.getters.sqlEditorContainer().find('.cm-content').type('{end} LIMIT 10').type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.openNode('Postgres');
|
||||
ndv.getters.sqlEditorContainer().should('contain', 'SELECT * FROM `testTable` LIMIT 10');
|
||||
});
|
||||
|
||||
it('should update expression output dropdown as the query is edited', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('MySQL', {
|
||||
action: 'Execute a SQL query',
|
||||
});
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openNode('When clicking "Test workflow"');
|
||||
ndv.actions.setPinnedData([{ table: 'test_table' }]);
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openNode('MySQL');
|
||||
ndv.getters
|
||||
.sqlEditorContainer()
|
||||
.find('.cm-content')
|
||||
.type('SELECT * FROM {{ $json.table }}', { parseSpecialCharSequences: false });
|
||||
workflowPage.getters
|
||||
.inlineExpressionEditorOutput()
|
||||
.should('have.text', 'SELECT * FROM test_table');
|
||||
});
|
||||
|
||||
it('should not push NDV header out with a lot of code in Postgres editor', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Postgres', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
cy.fixture('Dummy_javascript.txt').then((code) => {
|
||||
ndv.getters.sqlEditorContainer().find('.cm-content').paste(code);
|
||||
});
|
||||
ndv.getters.nodeExecuteButton().should('be.visible');
|
||||
});
|
||||
|
||||
it('should not push NDV header out with a lot of code in MySQL editor', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('MySQL', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
cy.fixture('Dummy_javascript.txt').then((code) => {
|
||||
ndv.getters.sqlEditorContainer().find('.cm-content').paste(code);
|
||||
});
|
||||
ndv.getters.nodeExecuteButton().should('be.visible');
|
||||
});
|
||||
});
|
169
cypress/e2e/41-editors.cy.ts
Normal file
169
cypress/e2e/41-editors.cy.ts
Normal file
|
@ -0,0 +1,169 @@
|
|||
import { WorkflowPage, NDV } from '../pages';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
// Update is debounced in editors, so adding typing delay to catch up
|
||||
const TYPING_DELAY = 100;
|
||||
|
||||
describe('Editors', () => {
|
||||
beforeEach(() => {
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
describe('SQL Editor', () => {
|
||||
|
||||
it('should preserve changes when opening-closing Postgres node', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Postgres', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
ndv.getters
|
||||
.sqlEditorContainer()
|
||||
.click()
|
||||
.find('.cm-content')
|
||||
.type('SELECT * FROM `testTable`', { delay: TYPING_DELAY })
|
||||
.type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.openNode('Postgres');
|
||||
ndv.getters.sqlEditorContainer().find('.cm-content').type('{end} LIMIT 10', { delay: TYPING_DELAY }).type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.openNode('Postgres');
|
||||
ndv.getters.sqlEditorContainer().should('contain', 'SELECT * FROM `testTable` LIMIT 10');
|
||||
});
|
||||
|
||||
it('should update expression output dropdown as the query is edited', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('MySQL', {
|
||||
action: 'Execute a SQL query',
|
||||
});
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openNode('When clicking "Test workflow"');
|
||||
ndv.actions.setPinnedData([{ table: 'test_table' }]);
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openNode('MySQL');
|
||||
ndv.getters
|
||||
.sqlEditorContainer()
|
||||
.find('.cm-content')
|
||||
.type('SELECT * FROM {{ $json.table }}', { parseSpecialCharSequences: false });
|
||||
workflowPage.getters
|
||||
.inlineExpressionEditorOutput()
|
||||
.should('have.text', 'SELECT * FROM test_table');
|
||||
});
|
||||
|
||||
it('should not push NDV header out with a lot of code in Postgres editor', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Postgres', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
cy.fixture('Dummy_javascript.txt').then((code) => {
|
||||
ndv.getters.sqlEditorContainer().find('.cm-content').paste(code);
|
||||
});
|
||||
ndv.getters.nodeExecuteButton().should('be.visible');
|
||||
});
|
||||
|
||||
it('should not push NDV header out with a lot of code in MySQL editor', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('MySQL', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
cy.fixture('Dummy_javascript.txt').then((code) => {
|
||||
ndv.getters.sqlEditorContainer().find('.cm-content').paste(code);
|
||||
});
|
||||
ndv.getters.nodeExecuteButton().should('be.visible');
|
||||
});
|
||||
|
||||
it('should not trigger dirty flag if nothing is changed', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Postgres', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
workflowPage.getters.isWorkflowSaved();
|
||||
workflowPage.actions.openNode('Postgres');
|
||||
ndv.actions.close();
|
||||
// Workflow should still be saved
|
||||
workflowPage.getters.isWorkflowSaved();
|
||||
});
|
||||
|
||||
it('should trigger dirty flag if query is updated', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Postgres', {
|
||||
action: 'Execute a SQL query',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
workflowPage.getters.isWorkflowSaved();
|
||||
workflowPage.actions.openNode('Postgres');
|
||||
ndv.getters
|
||||
.sqlEditorContainer()
|
||||
.click()
|
||||
.find('.cm-content')
|
||||
.type('SELECT * FROM `testTable`', { delay: TYPING_DELAY })
|
||||
.type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.getters.isWorkflowSaved().should('not.be.true');
|
||||
});
|
||||
});
|
||||
|
||||
describe('HTML Editor', () => {
|
||||
// Closing tags will be added by the editor
|
||||
const TEST_ELEMENT_H1 = '<h1>Test';
|
||||
const TEST_ELEMENT_P = '<p>Test';
|
||||
|
||||
it('should preserve changes when opening-closing HTML node', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('HTML', {
|
||||
action: 'Generate HTML template',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
ndv.getters
|
||||
.htmlEditorContainer()
|
||||
.click()
|
||||
.find('.cm-content')
|
||||
.type(`{selectall}${TEST_ELEMENT_H1}`, { delay: TYPING_DELAY, force: true })
|
||||
.type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.openNode('HTML');
|
||||
ndv.getters.htmlEditorContainer().find('.cm-content').type(`{end}${TEST_ELEMENT_P}`, { delay: TYPING_DELAY, force: true }).type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.openNode('HTML');
|
||||
ndv.getters.htmlEditorContainer().should('contain', TEST_ELEMENT_H1);
|
||||
ndv.getters.htmlEditorContainer().should('contain', TEST_ELEMENT_P);
|
||||
});
|
||||
|
||||
it('should not trigger dirty flag if nothing is changed', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('HTML', {
|
||||
action: 'Generate HTML template',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
workflowPage.getters.isWorkflowSaved();
|
||||
workflowPage.actions.openNode('HTML');
|
||||
ndv.actions.close();
|
||||
// Workflow should still be saved
|
||||
workflowPage.getters.isWorkflowSaved();
|
||||
});
|
||||
|
||||
it('should trigger dirty flag if query is updated', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('HTML', {
|
||||
action: 'Generate HTML template',
|
||||
keepNdvOpen: true,
|
||||
});
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
workflowPage.getters.isWorkflowSaved();
|
||||
workflowPage.actions.openNode('HTML');
|
||||
ndv.getters
|
||||
.htmlEditorContainer()
|
||||
.click()
|
||||
.find('.cm-content')
|
||||
.type(`{selectall}${TEST_ELEMENT_H1}`, { delay: TYPING_DELAY, force: true })
|
||||
.type('{esc}');
|
||||
ndv.actions.close();
|
||||
workflowPage.getters.isWorkflowSaved().should('not.be.true');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -84,6 +84,7 @@ export class NDV extends BasePage {
|
|||
cy.getByTestId('columns-parameter-input-options-container'),
|
||||
resourceMapperRemoveAllFieldsOption: () => cy.getByTestId('action-removeAllFields'),
|
||||
sqlEditorContainer: () => cy.getByTestId('sql-editor-container'),
|
||||
htmlEditorContainer: () => cy.getByTestId('html-editor-container'),
|
||||
filterComponent: (paramName: string) => cy.getByTestId(`filter-${paramName}`),
|
||||
filterCombinator: (paramName: string, index = 0) =>
|
||||
this.getters.filterComponent(paramName).getByTestId('filter-combinator-select').eq(index),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div :class="$style.editor">
|
||||
<div ref="htmlEditor"></div>
|
||||
<div ref="htmlEditor" data-test-id="html-editor-container"></div>
|
||||
<slot name="suffix" />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -244,7 +244,6 @@ onMounted(() => {
|
|||
|
||||
onBeforeUnmount(() => {
|
||||
htmlEditorEventBus.off('format-html', formatHtml);
|
||||
emit('update:model-value', readEditorValue());
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1189,6 +1189,13 @@ function valueChanged(value: NodeParameterValueType | {} | Date) {
|
|||
if (remoteParameterOptionsLoading.value) {
|
||||
return;
|
||||
}
|
||||
// Only update the value if it has changed
|
||||
const oldValue = node.value?.parameters
|
||||
? nodeHelpers.getParameterValue(node.value?.parameters, props.parameter.name, '')
|
||||
: undefined;
|
||||
if (oldValue !== undefined && oldValue === value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.parameter.name === 'nodeCredentialType') {
|
||||
activeCredentialType.value = value as string;
|
||||
|
|
|
@ -163,7 +163,6 @@ onMounted(() => {
|
|||
|
||||
onBeforeUnmount(() => {
|
||||
codeNodeEditorEventBus.off('error-line-number', highlightLine);
|
||||
emit('update:model-value', readEditorValue());
|
||||
});
|
||||
|
||||
function line(lineNumber: number): Line | null {
|
||||
|
|
Loading…
Reference in a new issue