botium-core
Version:
The Selenium for Chatbots
402 lines (351 loc) • 15.3 kB
JavaScript
const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
chai.use(chaiAsPromised)
const assert = chai.assert
const BotDriver = require('../../').BotDriver
const Capabilities = require('../../').Capabilities
const nock = require('nock')
const myCapsGet = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint/{{msg.messageText}}',
[Capabilities.SIMPLEREST_HEADERS_TEMPLATE]: { HEADER1: 'HEADER1VALUE', HEADER2: '{{msg.token}}' },
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$'
}
const myCapsPost = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint',
[Capabilities.SIMPLEREST_METHOD]: 'POST',
[Capabilities.SIMPLEREST_HEADERS_TEMPLATE]: { HEADER1: 'HEADER1VALUE', HEADER2: '{{msg.token}}' },
[Capabilities.SIMPLEREST_BODY_TEMPLATE]: { BODY1: 'BODY1VALUE', BODY2: '{{msg.messageText}}' },
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$'
}
const myCapsScriptingMemory = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint',
[Capabilities.SIMPLEREST_METHOD]: 'POST',
[Capabilities.SIMPLEREST_BODY_TEMPLATE]: {
FUNCTION_WITHOUT_PARAM: '{{fnc.year}}',
FUNCTION_WITH_PARAM: '{{#fnc.random}}5{{/fnc.random}}',
FUNCTION_WITH_PARAM_FROM_SCRIPTING_MEMORY: '{{#fnc.random}}{{msg.scriptingMemory.functionArgument}}{{/fnc.random}}',
USING_CODE: '{{#fnc.func}}1 + 2{{/fnc.func}}',
VARIABLE: '{{msg.scriptingMemory.variable}}'
},
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$'
}
const myCapsStringTemplate = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint',
[Capabilities.SIMPLEREST_METHOD]: 'POST',
[Capabilities.SIMPLEREST_BODY_TEMPLATE]: '{ "timestamp": "{{fnc.now_DE}}" }',
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$'
}
const myCapsConvAndStepId = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint',
[Capabilities.SIMPLEREST_METHOD]: 'POST',
[Capabilities.SIMPLEREST_CONVERSATION_ID_TEMPLATE]: '{{fnc.timestamp}}',
[Capabilities.SIMPLEREST_STEP_ID_TEMPLATE]: '{{#fnc.random}}7{{/fnc.random}}',
[Capabilities.SIMPLEREST_BODY_TEMPLATE]: { SESSION_ID: '{{botium.conversationId}}', MESSAGE_ID: '{{botium.stepId}}' },
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$'
}
const myCapsHookBase = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint',
[Capabilities.SIMPLEREST_METHOD]: 'POST',
[Capabilities.SIMPLEREST_BODY_TEMPLATE]: { SESSION_ID: '{{botium.conversationId}}', MESSAGE_ID: '{{botium.stepId}}' },
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$'
}
const myCapsRequestHookFromString = Object.assign({
[Capabilities.SIMPLEREST_REQUEST_HOOK]: `
let counter = 1
requestOptions.body = {bodyFieldRequestHook: counter++}
context.contextFieldRequestHook = counter
`
}, myCapsHookBase)
const myCapsRequestHookFromStringInvalid = Object.assign({
[Capabilities.SIMPLEREST_REQUEST_HOOK]: '!'
}, myCapsHookBase)
const myCapsRequestHookFromFunction = Object.assign({
[Capabilities.SIMPLEREST_REQUEST_HOOK]: ({ requestOptions, context }) => {
let counter = 1
requestOptions.body = { bodyFieldRequestHook: counter++ }
context.contextFieldRequestHook = counter
}
}, myCapsHookBase)
const myCapsRequestHookFromModule = Object.assign({
// path relative to SimpleRestContainer???
[Capabilities.SIMPLEREST_REQUEST_HOOK]: '../../../test/connectors/logicHook'
}, myCapsHookBase)
const myCapsResponseHook = Object.assign({
[Capabilities.SIMPLEREST_RESPONSE_HOOK]: `
botMsg.messageText = responseJsonPathKey ? 'message text from hook' : ('messageText found by' + responseJsonPathKey)
`
}, myCapsHookBase)
const msg = {
messageText: 'messageText',
token: 'myToken',
scriptingMemory: {
variable: 'value',
functionArgument: '7'
}
}
const _assertHook = async (myCaps) => {
const driver = new BotDriver(myCaps)
const container = await driver.Build()
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.exists(request.body)
assert.exists(request.body.bodyFieldRequestHook)
assert.equal(request.body.bodyFieldRequestHook, 1)
assert.exists(container.pluginInstance.view)
assert.exists(container.pluginInstance.view.context)
assert.exists(container.pluginInstance.view.context.contextFieldRequestHook)
assert.equal(container.pluginInstance.view.context.contextFieldRequestHook, 2)
await container.Clean()
}
describe('connectors.simplerest.nock', function () {
it('should build JSON GET url', async () => {
const caps = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint/{{msg.messageText}}',
[Capabilities.SIMPLEREST_HEADERS_TEMPLATE]: { HEADER1: 'HEADER1VALUE', HEADER2: '{{msg.token}}' },
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$',
[Capabilities.SIMPLEREST_PING_URL]: 'https://mock.com/pingget'
}
const scope = nock('https://mock.com')
.get('/pingget')
.reply(200, {
status: 'ok'
})
.persist()
const driver = new BotDriver(caps)
const container = await driver.Build()
const body = JSON.stringify({})
const pingConfig = {
method: 'GET',
uri: 'https://mock.com/pingget',
body: body,
timeout: 10000
}
const response = await container.pluginInstance._waitForPingUrl(pingConfig, 2)
assert.equal(response.body, '{"status":"ok"}')
scope.persist(false)
})
it('post ping endpoint', async () => {
const caps = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint/{{msg.messageText}}',
[Capabilities.SIMPLEREST_HEADERS_TEMPLATE]: { HEADER1: 'HEADER1VALUE', HEADER2: '{{msg.token}}' },
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$',
[Capabilities.SIMPLEREST_PING_URL]: 'https://mock.com/pingpost',
[Capabilities.SIMPLEREST_PING_RETRIES]: 2
}
const scope = nock('https://mock.com')
.post('/pingpost', { status: 'ok?' }, null)
.reply(200, {
status: 'ok'
})
.persist()
const driver = new BotDriver(caps)
const container = await driver.Build()
const body = JSON.stringify({ status: 'ok?' })
const pingConfig = {
method: 'POST',
uri: 'https://mock.com/pingpost',
body: body,
timeout: 100
}
const response = await container.pluginInstance._waitForPingUrl(pingConfig, 2)
assert.equal(response.body, '{"status":"ok"}')
scope.persist(false)
})
it('error case can\'t connect', async () => {
const caps = {
[Capabilities.CONTAINERMODE]: 'simplerest',
[Capabilities.SIMPLEREST_URL]: 'http://my-host.com/api/endpoint/{{msg.messageText}}',
[Capabilities.SIMPLEREST_HEADERS_TEMPLATE]: { HEADER1: 'HEADER1VALUE', HEADER2: '{{msg.token}}' },
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$',
[Capabilities.SIMPLEREST_PING_URL]: 'https://mock.com/pingfail',
[Capabilities.SIMPLEREST_PING_RETRIES]: 2
}
const scope = nock('https://mock.com')
.get('/pingfail')
.reply(404, {
error: 'notOk'
})
.persist()
const driver = new BotDriver(caps)
const container = await driver.Build()
const body = JSON.stringify({})
const pingConfig = {
method: 'GET',
uri: 'https://mock.com/pingfail',
body: body,
timeout: 100
}
try {
await container.pluginInstance._waitForPingUrl(pingConfig, 2)
assert.fail('expected ping error')
} catch (err) {
}
scope.persist(false)
})
})
describe('connectors.simplerest.build', function () {
it('should build JSON GET url', async function () {
const myCaps = Object.assign({}, myCapsGet)
const driver = new BotDriver(myCaps)
const container = await driver.Build()
assert.equal(container.pluginInstance.constructor.name, 'SimpleRestContainer')
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.isUndefined(request.json)
assert.isObject(request.headers)
assert.isUndefined(request.body)
assert.equal(request.headers.HEADER2, msg.token)
assert.equal(request.uri, 'http://my-host.com/api/endpoint/messageText')
await container.Clean()
})
it('should build JSON GET url from encoded characters', async function () {
const myCaps = Object.assign({}, myCapsGet)
myCaps[Capabilities.SIMPLEREST_HEADERS_TEMPLATE] = { ORIG: '{{{msg.messageText}}}' }
const myMsg = Object.assign({}, msg)
myMsg.messageText = '&?äüö'
const driver = new BotDriver(myCaps)
const container = await driver.Build()
assert.equal(container.pluginInstance.constructor.name, 'SimpleRestContainer')
await container.Start()
const request = container.pluginInstance._buildRequest(myMsg)
assert.isUndefined(request.json)
assert.isObject(request.headers)
assert.isUndefined(request.body)
assert.equal(request.headers.ORIG, myMsg.messageText)
assert.equal(request.uri, 'http://my-host.com/api/endpoint/' + encodeURIComponent(myMsg.messageText))
await container.Clean()
})
it('should build JSON POST request body', async function () {
const myCaps = Object.assign({}, myCapsPost)
const driver = new BotDriver(myCaps)
const container = await driver.Build()
assert.equal(container.pluginInstance.constructor.name, 'SimpleRestContainer')
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.isTrue(request.json)
assert.isObject(request.headers)
assert.isObject(request.body)
assert.equal(request.headers.HEADER2, msg.token)
assert.equal(request.body.BODY2, msg.messageText)
await container.Clean()
})
it('should build JSON POST request body from strings', async function () {
const myCaps = Object.assign({}, myCapsPost)
myCaps[Capabilities.SIMPLEREST_BODY_TEMPLATE] = JSON.stringify(myCaps[Capabilities.SIMPLEREST_BODY_TEMPLATE])
myCaps[Capabilities.SIMPLEREST_HEADERS_TEMPLATE] = JSON.stringify(myCaps[Capabilities.SIMPLEREST_HEADERS_TEMPLATE])
const driver = new BotDriver(myCaps)
const container = await driver.Build()
assert.equal(container.pluginInstance.constructor.name, 'SimpleRestContainer')
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.isTrue(request.json)
assert.isObject(request.headers)
assert.isObject(request.body)
assert.equal(request.headers.HEADER2, msg.token)
assert.equal(request.body.BODY2, msg.messageText)
await container.Clean()
})
it('should build url-form-encoded POST request body', async function () {
const myCaps = Object.assign({}, myCapsPost)
myCaps[Capabilities.SIMPLEREST_BODY_RAW] = true
myCaps[Capabilities.SIMPLEREST_HEADERS_TEMPLATE] = { 'Content-Type': 'application/x-www-form-urlencoded' }
myCaps[Capabilities.SIMPLEREST_BODY_TEMPLATE] = 'BODY1=BODY1VALUE&BODY2={{msg.messageText}}'
const driver = new BotDriver(myCaps)
const container = await driver.Build()
assert.equal(container.pluginInstance.constructor.name, 'SimpleRestContainer')
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.isObject(request.headers)
assert.isString(request.body)
assert.equal(request.body, 'BODY1=BODY1VALUE&BODY2=messageText')
await container.Clean()
})
it('should use scriptingMemory variables', async function () {
const myCaps = Object.assign({}, myCapsScriptingMemory)
const driver = new BotDriver(myCaps)
const container = await driver.Build()
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.isTrue(request.json)
assert.exists(request.body)
assert.exists(request.body.FUNCTION_WITHOUT_PARAM)
assert.equal(request.body.FUNCTION_WITHOUT_PARAM.length, 4)
assert.exists(request.body.FUNCTION_WITH_PARAM)
assert.equal(request.body.FUNCTION_WITH_PARAM.length, 5)
assert.exists(request.body.FUNCTION_WITH_PARAM_FROM_SCRIPTING_MEMORY)
assert.equal(request.body.FUNCTION_WITH_PARAM_FROM_SCRIPTING_MEMORY.length, 7)
assert.exists(request.body.USING_CODE)
assert.equal(request.body.USING_CODE, 3)
assert.exists(request.body.VARIABLE)
assert.equal(request.body.VARIABLE, 'value')
await container.Clean()
})
it('should parse string template', async function () {
const myCaps = Object.assign({}, myCapsStringTemplate)
const driver = new BotDriver(myCaps)
const container = await driver.Build()
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.isTrue(request.json)
assert.exists(request.body)
assert.exists(request.body.timestamp)
await container.Clean()
})
it('should use scriptingMemory variables for step, and conversation id if template is set', async function () {
const myCaps = Object.assign({}, myCapsConvAndStepId)
const driver = new BotDriver(myCaps)
const container = await driver.Build()
await container.Start()
const request = container.pluginInstance._buildRequest(msg)
assert.isTrue(request.json)
assert.exists(request.body)
assert.exists(request.body.SESSION_ID)
assert.equal(request.body.SESSION_ID.length, 13)
assert.exists(request.body.MESSAGE_ID)
assert.equal(request.body.MESSAGE_ID.length, 7)
await container.Clean()
})
it('should use request hook, from string', async function () {
await _assertHook(Object.assign({}, myCapsRequestHookFromString))
})
it('should use request hook, from function', async function () {
await _assertHook(Object.assign({}, myCapsRequestHookFromFunction))
})
it('should use request hook, from function2', async function () {
await _assertHook(Object.assign({}, myCapsRequestHookFromFunction))
})
it('should use request hook, from module', async function () {
await _assertHook(Object.assign({}, myCapsRequestHookFromModule))
})
it('should use request hook, from invalid string', async function () {
const driver = new BotDriver(myCapsRequestHookFromStringInvalid)
try {
await driver.Build()
assert.fail('it should have failed')
} catch (err) {
assert.isTrue(err.message.includes('Cant load hook, syntax is not valid'))
}
})
})
describe('connectors.simplerest.processBody', function () {
it('should build JSON GET url', async function () {
const myCaps = Object.assign({}, myCapsResponseHook)
const driver = new BotDriver(myCaps)
const container = await driver.Build()
assert.equal(container.pluginInstance.constructor.name, 'SimpleRestContainer')
await container.Start()
const msgs = container.pluginInstance._processBodyAsyncImpl({}, true)
assert.exists(msgs)
assert.equal(msgs.length, 1)
assert.equal(msgs[0].messageText, 'message text from hook')
await container.Clean()
})
})