diff --git a/e2e_tests/integration/multistatements.spec.js b/e2e_tests/integration/multistatements.spec.js index 9de44174342..48f6e0248cf 100644 --- a/e2e_tests/integration/multistatements.spec.js +++ b/e2e_tests/integration/multistatements.spec.js @@ -18,9 +18,21 @@ * along with this program. If not, see . */ -/* global Cypress, cy, test, expect */ +/* global Cypress, cy, test, expect, before, after */ describe('Multi statements', () => { + const validQuery = 'RETURN 1; :config; RETURN 2;' + + before(() => { + cy.get('[data-test-id="drawerSettings"]').click() + cy.get('[data-test-id="enableMultiStatementMode"]').click() + cy.get('[data-test-id="drawerSettings"]').click() + }) + after(() => { + cy.get('[data-test-id="drawerSettings"]').click() + cy.get('[data-test-id="enableMultiStatementMode"]').click() + cy.get('[data-test-id="drawerSettings"]').click() + }) it('can connect', () => { const password = Cypress.env('browser-password') || 'newpassword' cy.connect( @@ -30,8 +42,7 @@ describe('Multi statements', () => { }) it('can run multiple statements (non open by default)', () => { cy.executeCommand(':clear') - const query = 'RETURN 1; :config; RETURN 2;' - cy.executeCommand(query) + cy.executeCommand(validQuery) cy.get('[data-test-id="frame"]', { timeout: 10000 }).should( 'have.length', 1 @@ -45,6 +56,32 @@ describe('Multi statements', () => { .get('[data-test-id="multi-statement-list-content"]') .should('have.length', 0) }) + + it('can force run multiple statements to be executed as one statement', () => { + // Given + cy.executeCommand(':clear') + cy.get('[data-test-id="drawerSettings"]').click() + cy.get('[data-test-id="enableMultiStatementMode"]').click() + cy.get('[data-test-id="drawerSettings"]').click() + + // When + cy.executeCommand(validQuery) + cy.waitForCommandResult() + + // Then + // Error expected + cy.get('[data-test-id="frameCommand"]', { timeout: 10000 }) + .first() + .should('contain', validQuery) + cy.get('[data-test-id="frameStatusbar"]', { timeout: 10000 }) + .first() + .should('contain', 'Error') + + cy.get('[data-test-id="drawerSettings"]').click() + cy.get('[data-test-id="enableMultiStatementMode"]').click() + cy.get('[data-test-id="drawerSettings"]').click() + }) + it('can run multiple statements with error open', () => { cy.executeCommand(':clear') const query = 'RETURN 1; RETURN $nonsetparam; RETURN 2;' diff --git a/src/browser/modules/Sidebar/Settings.jsx b/src/browser/modules/Sidebar/Settings.jsx index a93d1dd3ea6..659fcf34cb9 100644 --- a/src/browser/modules/Sidebar/Settings.jsx +++ b/src/browser/modules/Sidebar/Settings.jsx @@ -53,6 +53,13 @@ const visualSettings = [ tooltip: 'Autocomplete and syntax highlighting in query editor', type: 'checkbox' } + }, + { + enableMultiStatementMode: { + displayName: 'Enable multi statement query editor', + tooltip: 'Allows query editor to execute multiple statements', + type: 'checkbox' + } } ] }, @@ -193,6 +200,7 @@ export const Settings = ({ onSettingsSave(settings) }} checked={settings[setting]} + data-test-id={setting} /> {visual} diff --git a/src/shared/modules/commands/commandsDuck.js b/src/shared/modules/commands/commandsDuck.js index 42e2c283310..e069593e22c 100644 --- a/src/shared/modules/commands/commandsDuck.js +++ b/src/shared/modules/commands/commandsDuck.js @@ -34,7 +34,11 @@ import { } from 'services/utils' import helper from 'services/commandInterpreterHelper' import { addHistory } from '../history/historyDuck' -import { getCmdChar, getMaxHistory } from '../settings/settingsDuck' +import { + getCmdChar, + getMaxHistory, + shouldEnableMultiStatementMode +} from '../settings/settingsDuck' import { fetchRemoteGuide } from './helpers/play' import { CONNECTION_SUCCESS } from '../connections/connectionsDuck' import { @@ -137,7 +141,10 @@ export const handleCommandEpic = (action$, store) => store.dispatch(clearErrorMessage()) const maxHistory = getMaxHistory(store.getState()) store.dispatch(addHistory(action.cmd, maxHistory)) - const statements = extractStatementsFromString(action.cmd) + const statements = shouldEnableMultiStatementMode(store.getState()) + ? extractStatementsFromString(action.cmd) + : [action.cmd] + if (!statements.length || !statements[0]) { return } diff --git a/src/shared/modules/commands/multiCommands.test.js b/src/shared/modules/commands/multiCommands.test.js index d455f9a98c1..a194323cdb6 100644 --- a/src/shared/modules/commands/multiCommands.test.js +++ b/src/shared/modules/commands/multiCommands.test.js @@ -47,7 +47,8 @@ describe('handleCommandEpic', () => { store = mockStore({ settings: { cmdchar: ':', - maxHistory: maxHistory + maxHistory: maxHistory, + enableMultiStatementMode: true }, history: [':xxx'], connections: {}, diff --git a/src/shared/modules/settings/__snapshots__/settingsDuck.test.js.snap b/src/shared/modules/settings/__snapshots__/settingsDuck.test.js.snap index c1a55a2b6e5..c811e8fa738 100644 --- a/src/shared/modules/settings/__snapshots__/settingsDuck.test.js.snap +++ b/src/shared/modules/settings/__snapshots__/settingsDuck.test.js.snap @@ -7,6 +7,7 @@ Object { "cmdchar": ":", "editorAutocomplete": true, "editorLint": false, + "enableMultiStatementMode": false, "initCmd": ":play start", "initialNodeDisplay": 300, "maxFrames": 30, diff --git a/src/shared/modules/settings/settingsDuck.js b/src/shared/modules/settings/settingsDuck.js index a8b60c1dab0..7f0f49dc565 100644 --- a/src/shared/modules/settings/settingsDuck.js +++ b/src/shared/modules/settings/settingsDuck.js @@ -44,6 +44,8 @@ export const getScrollToTop = state => state[NAME].scrollToTop export const shouldReportUdc = state => state[NAME].shouldReportUdc !== false export const shouldAutoComplete = state => state[NAME].autoComplete !== false export const shouldEditorLint = state => state[NAME].editorLint === true +export const shouldEnableMultiStatementMode = state => + state[NAME].enableMultiStatementMode const browserSyncConfig = (host = 'https://auth.neo4j.com') => ({ authWindowUrl: `${host}/indexNewBrowser.html`, @@ -79,7 +81,8 @@ const initialState = { maxFrames: 30, editorAutocomplete: true, editorLint: false, - useCypherThread: true + useCypherThread: true, + enableMultiStatementMode: false } export default function settings (state = initialState, action) {