Skip to content

Commit

Permalink
fix(editor): Prevent updating node parameter value if it hasn't chang…
Browse files Browse the repository at this point in the history
…ed (#9535)
  • Loading branch information
MiloradFilipovic authored May 29, 2024
1 parent f914c97 commit 63990f1
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 74 deletions.
71 changes: 0 additions & 71 deletions cypress/e2e/29-sql-editor.cy.ts

This file was deleted.

169 changes: 169 additions & 0 deletions cypress/e2e/41-editors.cy.ts
Original file line number Diff line number Diff line change
@@ -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');
});
});
});
1 change: 1 addition & 0 deletions cypress/pages/ndv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
3 changes: 1 addition & 2 deletions packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -244,7 +244,6 @@ onMounted(() => {
onBeforeUnmount(() => {
htmlEditorEventBus.off('format-html', formatHtml);
emit('update:model-value', readEditorValue());
});
</script>

Expand Down
7 changes: 7 additions & 0 deletions packages/editor-ui/src/components/ParameterInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion packages/editor-ui/src/components/SqlEditor/SqlEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ onMounted(() => {
onBeforeUnmount(() => {
codeNodeEditorEventBus.off('error-line-number', highlightLine);
emit('update:model-value', readEditorValue());
});
function line(lineNumber: number): Line | null {
Expand Down

0 comments on commit 63990f1

Please sign in to comment.