diff --git a/src/shared/modules/commands/commandsDuck.js b/src/shared/modules/commands/commandsDuck.js index 4c9b310f9d3..7fe35d880f9 100644 --- a/src/shared/modules/commands/commandsDuck.js +++ b/src/shared/modules/commands/commandsDuck.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -import { getInterpreter, isNamedInterpreter, cleanCommand } from 'services/commandUtils' +import { getInterpreter, isNamedInterpreter, cleanCommand, extractPostConnectCommandsFromServerConfig } from 'services/commandUtils' import { hydrate } from 'services/duckUtils' import helper from 'services/commandInterpreterHelper' import { addHistory } from '../history/historyDuck' @@ -134,7 +134,12 @@ export const postConnectCmdEpic = (some$, store) => const serverSettings = getAvailableSettings(store.getState()) if (serverSettings && serverSettings['browser.post_connect_cmd']) { const cmdchar = getCmdChar(store.getState()) - store.dispatch(executeSystemCommand(`${cmdchar}${serverSettings['browser.post_connect_cmd']}`)) + const cmds = extractPostConnectCommandsFromServerConfig(serverSettings['browser.post_connect_cmd']) + if (cmds !== undefined) { + cmds.forEach((cmd) => { + store.dispatch(executeSystemCommand(`${cmdchar}${cmd}`)) + }) + } } }) .mapTo({ type: 'NOOP' }) diff --git a/src/shared/modules/commands/postConnectCmdEpic.test.js b/src/shared/modules/commands/postConnectCmdEpic.test.js index 5afc36a065b..bd4beeb111d 100644 --- a/src/shared/modules/commands/postConnectCmdEpic.test.js +++ b/src/shared/modules/commands/postConnectCmdEpic.test.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -/* global describe, afterEach, test, expect */ +/* global describe, test, expect */ import configureMockStore from 'redux-mock-store' import { createEpicMiddleware } from 'redux-observable' import { createBus, createReduxMiddleware } from 'suber' @@ -27,18 +27,14 @@ import { UPDATE_SETTINGS } from 'shared/modules/dbMeta/dbMetaDuck' import * as commands from './commandsDuck' import { CONNECTION_SUCCESS } from 'shared/modules/connections/connectionsDuck' -const bus = createBus() -const epicMiddleware = createEpicMiddleware(commands.postConnectCmdEpic) -const mockStore = configureMockStore([epicMiddleware, createReduxMiddleware(bus)]) - describe('postConnectCmdEpic', () => { - afterEach(() => { - bus.reset() - }) test('creates a SYSTEM_COMMAND_QUEUED if found', (done) => { // Given + const bus = createBus() + const epicMiddlewareLocal = createEpicMiddleware(commands.postConnectCmdEpic) + const mockStoreLocal = configureMockStore([epicMiddlewareLocal, createReduxMiddleware(bus)]) const command = 'play hello' - const store = mockStore({ + const store = mockStoreLocal({ settings: { cmdchar: ':' }, @@ -65,9 +61,48 @@ describe('postConnectCmdEpic', () => { store.dispatch(action) store.dispatch(action2) }) - test.skip('does nothing if settings not found', (done) => { // Ignore for now. Some bug in mockStore that breaks this test + test('supports multiple commands', (done) => { + // Given + const command1 = 'play hello' + const command2 = 'play intro' + const command = command1 + '; ' + command2 + const bus = createBus() + const epicMiddlewareLocal = createEpicMiddleware(commands.postConnectCmdEpic) + const mockStoreLocal = configureMockStore([epicMiddlewareLocal, createReduxMiddleware(bus)]) + const store = mockStoreLocal({ + settings: { + cmdchar: ':' + }, + meta: { + settings: { + 'browser.post_connect_cmd': command + } + } + }) + const action = { type: CONNECTION_SUCCESS } + const action2 = { type: UPDATE_SETTINGS } + bus.take('NOOP', (currentAction) => { + // Then + expect(store.getActions()).toEqual([ + action, + action2, + commands.executeSystemCommand(':' + command1), + commands.executeSystemCommand(':' + command2), + { type: 'NOOP' } + ]) + done() + }) + + // When + store.dispatch(action) + store.dispatch(action2) + }) + test('does nothing if settings not found', (done) => { // Given - const store = mockStore({ + const bus = createBus() + const epicMiddlewareLocal = createEpicMiddleware(commands.postConnectCmdEpic) + const mockStoreLocal = configureMockStore([epicMiddlewareLocal, createReduxMiddleware(bus)]) + const store = mockStoreLocal({ settings: { cmdchar: ':' }, diff --git a/src/shared/services/commandUtils.js b/src/shared/services/commandUtils.js index a1bc3795e1e..cc4b0615e32 100644 --- a/src/shared/services/commandUtils.js +++ b/src/shared/services/commandUtils.js @@ -85,3 +85,21 @@ export const getInterpreter = (interpret, cmd, cmdchar) => { } export const isNamedInterpreter = (interpreter) => interpreter && interpreter.name !== 'catch-all' + +export const extractPostConnectCommandsFromServerConfig = (str) => { + const substituteStr = '@@semicolon@@' + const substituteRe = new RegExp(substituteStr, 'g') + const replaceFn = (m) => m.replace(/;/g, substituteStr) + const qs = [ + /(`[^`]*?`)/g, + /("[^"]*?")/g, + /('[^']*?')/g + ] + qs.forEach((q) => (str = str.replace(q, replaceFn))) + const splitted = str + .split(';') + .map((item) => item.trim()) + .map((item) => item.replace(substituteRe, ';')) + .filter((item) => item && item.length) + return splitted && splitted.length ? splitted : undefined +} diff --git a/src/shared/services/commandUtils.test.js b/src/shared/services/commandUtils.test.js index 0a4ca364684..2db2efa43c2 100644 --- a/src/shared/services/commandUtils.test.js +++ b/src/shared/services/commandUtils.test.js @@ -115,4 +115,28 @@ describe('commandutils', () => { expect(obj.str + ': ' + utils.isCypherCommand(obj.str, ':')).toEqual(obj.str + ': ' + obj.expect) }) }) + test('extractPostConnectCommandsFromServerConfig should split and return an array of commands', () => { + // Given + const testStrs = [ + { str: '', expect: undefined }, + { str: ';;;;;;;;', expect: undefined }, + { str: ':play cypher', expect: [':play cypher'] }, + { str: ' :play cypher ', expect: [':play cypher'] }, + { str: ':play cypher;', expect: [':play cypher'] }, + { str: ':play cypher ;', expect: [':play cypher'] }, + { str: ';:play cypher;', expect: [':play cypher'] }, + { str: ':play cypher; :param x: 1', expect: [':play cypher', ':param x: 1'] }, + { str: 'RETURN 1; RETURN 3; :play start', expect: ['RETURN 1', 'RETURN 3', ':play start'] }, + { str: 'MATCH (n: {foo: "bar;", bar: "foo;"}) RETURN n', expect: ['MATCH (n: {foo: "bar;", bar: "foo;"}) RETURN n'] }, + { str: 'MATCH (n: {foo: \'bar;\'}) RETURN n', expect: ['MATCH (n: {foo: \'bar;\'}) RETURN n'] }, + { str: 'MATCH (n: {foo: `bar;`}) RETURN n', expect: ['MATCH (n: {foo: `bar;`}) RETURN n'] }, + { str: 'MATCH (n: {foo: `bar;;`}) RETURN n', expect: ['MATCH (n: {foo: `bar;;`}) RETURN n'] }, + { str: ':play cypher; MATCH (n: {foo: `bar; en;`}) RETURN n', expect: [':play cypher', 'MATCH (n: {foo: `bar; en;`}) RETURN n'] } + ] + + // When & Then + testStrs.forEach((item) => { + expect(utils.extractPostConnectCommandsFromServerConfig(item.str)).toEqual(item.expect) + }) + }) })