diff --git a/__mocks__/env.js b/__mocks__/env.js new file mode 100644 index 0000000..9f1706c --- /dev/null +++ b/__mocks__/env.js @@ -0,0 +1,22 @@ +const MOCK_DB = require('../packages/database/src/mock') +const PROVIDER_DB = require('../packages/provider/src/mock') + +/** + * Preparar env para el test + * @param {*} context + */ +const setup = async (context) => { + context.provider = new PROVIDER_DB() + context.database = new MOCK_DB() +} + +const clear = async (context) => { + context.provider = null + context.database = null +} + +function delay(ms) { + return new Promise((res) => setTimeout(res, ms)) +} + +module.exports = { setup, clear, delay } diff --git a/__mocks__/mobile.mock.js b/__mocks__/mobile.mock.js deleted file mode 100644 index 7f19f74..0000000 --- a/__mocks__/mobile.mock.js +++ /dev/null @@ -1,6 +0,0 @@ -const MOCK_MOBILE_WS = { - from: 'XXXXXX', - hasMedia: false, -} - -module.exports = { MOCK_MOBILE_WS } diff --git a/__mocks__/mock.provider.js b/__mocks__/mock.provider.js deleted file mode 100644 index 67b793e..0000000 --- a/__mocks__/mock.provider.js +++ /dev/null @@ -1,21 +0,0 @@ -const ProviderClass = require('../packages/bot/provider/provider.class') -class MockProvider extends ProviderClass { - constructor() { - super() - } - - delaySendMessage = (miliseconds, eventName, payload) => - new Promise((res) => - setTimeout(() => { - this.emit(eventName, payload) - res - }, miliseconds) - ) - - sendMessage = async (userId, message) => { - console.log(`Enviando... ${userId}, ${message}`) - return Promise.resolve({ userId, message }) - } -} - -module.exports = MockProvider diff --git a/__test__/00-case.test.js b/__test__/00-case.test.js new file mode 100644 index 0000000..eea982a --- /dev/null +++ b/__test__/00-case.test.js @@ -0,0 +1,52 @@ +const { suite } = require('uvu') +const assert = require('uvu/assert') +const { addKeyword, createBot, createFlow } = require('../packages/bot/index') +const { setup, clear, delay } = require('../__mocks__/env') + +const suiteCase = suite('Flujo: Simple') + +suiteCase.before.each(setup) +suiteCase.after.each(clear) + +suiteCase(`Responder a "hola"`, async ({ database, provider }) => { + const flow = addKeyword('hola').addAnswer('Buenas!').addAnswer('Como vamos!') + + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + await delay(0) + + assert.is('Buenas!', database.listHistory[0].answer) + assert.is('Como vamos!', database.listHistory[1].answer) + assert.is(undefined, database.listHistory[2]) +}) + +suiteCase(`NO reponder a "pepe"`, async ({ database, provider }) => { + const flow = addKeyword('hola').addAnswer('Buenas!').addAnswer('Como vamos!') + + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'pepe', + }) + + await delay(0) + + assert.is(undefined, database.listHistory[0]) + assert.is(undefined, database.listHistory[1]) +}) + +suiteCase.run() diff --git a/__test__/001-case.test.js b/__test__/001-case.test.js new file mode 100644 index 0000000..b421955 --- /dev/null +++ b/__test__/001-case.test.js @@ -0,0 +1,59 @@ +const { suite } = require('uvu') +const assert = require('uvu/assert') +const { addKeyword, createBot, createFlow } = require('../packages/bot/index') +const { setup, clear, delay } = require('../__mocks__/env') + +const suiteCase = suite('Flujo: regex') + +suiteCase.before.each(setup) +suiteCase.after.each(clear) + +suiteCase(`Responder a una expresion regular`, async ({ database, provider }) => { + const REGEX_CREDIT_NUMBER = `/(^4[0-9]{12}(?:[0-9]{3})?$)|(^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$)|(3[47][0-9]{13})|(^3(?:0[0-5]|[68][0-9])[0-9]{11}$)|(^6(?:011|5[0-9]{2})[0-9]{12}$)|(^(?:2131|1800|35\d{3})\d{11}$)/gm` + + const flow = addKeyword(REGEX_CREDIT_NUMBER, { regex: true }) + .addAnswer(`Gracias por proporcionar un numero de tarjeta valido`) + .addAnswer('Fin!') + + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: '374245455400126', + }) + + await delay(10) + + assert.is('Gracias por proporcionar un numero de tarjeta valido', database.listHistory[0].answer) + assert.is('Fin!', database.listHistory[1].answer) + assert.is(undefined, database.listHistory[2]) +}) + +suiteCase(`NO Responder a una expresion regular`, async ({ database, provider }) => { + const REGEX_CREDIT_NUMBER = `/(^4[0-9]{12}(?:[0-9]{3})?$)|(^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$)|(3[47][0-9]{13})|(^3(?:0[0-5]|[68][0-9])[0-9]{11}$)|(^6(?:011|5[0-9]{2})[0-9]{12}$)|(^(?:2131|1800|35\d{3})\d{11}$)/gm` + const flow = addKeyword(REGEX_CREDIT_NUMBER, { regex: true }) + .addAnswer(`Gracias por proporcionar un numero de tarjeta valido`) + .addAnswer('Fin!') + + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + await delay(10) + + assert.is(undefined, database.listHistory[0]) + assert.is(undefined, database.listHistory[1]) +}) + +suiteCase.run() diff --git a/__test__/01-case.test.js b/__test__/01-case.test.js index 57ae08c..7bca259 100644 --- a/__test__/01-case.test.js +++ b/__test__/01-case.test.js @@ -1,36 +1,51 @@ -const { test } = require('uvu') +const { suite } = require('uvu') const assert = require('uvu/assert') -const MOCK_DB = require('../packages/database/src/mock') -const PROVIDER_DB = require('../packages/provider/src/mock') -const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index') +const { addKeyword, createBot, createFlow } = require('../packages/bot/index') +const { setup, clear, delay } = require('../__mocks__/env') -test(`[Caso - 01] Flow Basico`, async () => { - const [VALUE_A, VALUE_B] = ['hola', 'buenas'] +const suiteCase = suite('Flujo: sensitive') - const flow = addKeyword(VALUE_A).addAnswer(VALUE_B) - const provider = createProvider(PROVIDER_DB) - const database = new MOCK_DB() +suiteCase.before.each(setup) +suiteCase.after.each(clear) + +suiteCase(`Responder a "ole" en minuscula`, async ({ database, provider }) => { + const flow = addKeyword(['ola', 'ole'], { sensitive: true }).addAnswer('Bienvenido a la OLA') createBot({ database, - flow: createFlow([flow]), provider, + flow: createFlow([flow]), }) - provider.delaySendMessage(100, 'message', { + await provider.delaySendMessage(0, 'message', { from: '000', - body: VALUE_A, + body: 'ole', }) - await delay(100) + await delay(0) - const prevMsg = database.getPrevByNumber('000') - - assert.is(prevMsg.answer, VALUE_B) + assert.is('Bienvenido a la OLA', database.listHistory[0].answer) + assert.is(undefined, database.listHistory[1]) }) -test.run() +suiteCase(`NO Responder a "ole" en minuscula`, async ({ database, provider }) => { + const flow = addKeyword(['ola', 'ole'], { sensitive: true }).addAnswer('Bienvenido a la OLA') -function delay(ms) { - return new Promise((res) => setTimeout(res, ms)) -} + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'OLE', + }) + + await delay(0) + + assert.is(undefined, database.listHistory[0]) + assert.is(undefined, database.listHistory[1]) +}) + +suiteCase.run() diff --git a/__test__/02-case.test.js b/__test__/02-case.test.js index a2a93ec..1d4c28d 100644 --- a/__test__/02-case.test.js +++ b/__test__/02-case.test.js @@ -1,99 +1,40 @@ -const { test } = require('uvu') +const { suite } = require('uvu') const assert = require('uvu/assert') -const MOCK_DB = require('../packages/database/src/mock') -const PROVIDER_DB = require('../packages/provider/src/mock') -const { - addKeyword, - createBot, - createFlow, - createProvider, -} = require('../packages/bot/index') +const { addKeyword, createBot, createFlow } = require('../packages/bot/index') +const { setup, clear, delay } = require('../__mocks__/env') -/** - * Falsear peticion async - * @param {*} fakeData - * @returns - */ -const fakeHTTP = async (fakeData = []) => { - console.log('⚡ Server request!') - await delay(50) - console.log('⚡ Server return!') - const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` })) - console.log(data) - return Promise.resolve(data) -} +const suiteCase = suite('Flujo: capture') -test(`[Caso - 02] Flow (flowDynamic)`, async () => { - const MOCK_VALUES = [ - 'Bienvenido te envio muchas marcas (5510)', - 'Seleccione marca del auto a cotizar, con el *número* correspondiente', - 'Seleccione la sub marca del auto a cotizar, con el *número* correspondiente:', - 'Los precios rondan:', - ] - const provider = createProvider(PROVIDER_DB) - const database = new MOCK_DB() +suiteCase.before.each(setup) +suiteCase.after.each(clear) - const flujoPrincipal = addKeyword(['hola']) - .addAnswer(MOCK_VALUES[0], null, async (ctx, { flowDynamic }) => { - console.log('execute...') - const data = await fakeHTTP(['Ford', 'GM', 'BMW']) - return flowDynamic(data) - }) - .addAnswer(MOCK_VALUES[1], null, async (ctx, { flowDynamic }) => { - const data = await fakeHTTP(['Ranger', 'Explorer']) - return flowDynamic(data) - }) - .addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => { - const data = await fakeHTTP(['Usado', 'Nuevos']) - return flowDynamic(data) - }) - .addAnswer(MOCK_VALUES[3], null, async (ctx, { flowDynamic }) => { - const data = await fakeHTTP(['1000', '2000', '3000']) - return flowDynamic(data) - }) +suiteCase(`Responder a "pregunta"`, async ({ database, provider }) => { + const flow = addKeyword(['hola']) + .addAnswer(['Hola como estas?', '¿Cual es tu edad?'], { capture: true }) + .addAnswer('Gracias por tu respuesta') createBot({ database, - flow: createFlow([flujoPrincipal]), provider, + flow: createFlow([flow]), }) - provider.delaySendMessage(0, 'message', { + await provider.delaySendMessage(0, 'message', { from: '000', body: 'hola', }) - await delay(1200) - const getHistory = database.listHistory.map((i) => i.answer) - assert.is(MOCK_VALUES[0], getHistory[0]) + await provider.delaySendMessage(10, 'message', { + from: '000', + body: '90', + }) - //FlowDynamic - assert.is('1 Ford', getHistory[1]) - assert.is('2 GM', getHistory[2]) - assert.is('3 BMW', getHistory[3]) + await delay(20) - assert.is(MOCK_VALUES[1], getHistory[4]) - - //FlowDynamic - assert.is('1 Ranger', getHistory[5]) - assert.is('2 Explorer', getHistory[6]) - - assert.is(MOCK_VALUES[2], getHistory[7]) - - //FlowDynamic - assert.is('1 Usado', getHistory[8]) - assert.is('2 Nuevos', getHistory[9]) - - assert.is(MOCK_VALUES[3], getHistory[10]) - - //FlowDynamic - assert.is('1 1000', getHistory[11]) - assert.is('2 2000', getHistory[12]) - assert.is('3 3000', getHistory[13]) + assert.is(['Hola como estas?', '¿Cual es tu edad?'].join('\n'), database.listHistory[0].answer) + assert.is('90', database.listHistory[1].answer) + assert.is('Gracias por tu respuesta', database.listHistory[2].answer) + assert.is(undefined, database.listHistory[3]) }) -test.run() - -function delay(ms) { - return new Promise((res) => setTimeout(res, ms)) -} +suiteCase.run() diff --git a/__test__/03-case.test.js b/__test__/03-case.test.js index 45c399a..6b9f7e8 100644 --- a/__test__/03-case.test.js +++ b/__test__/03-case.test.js @@ -1,44 +1,162 @@ -const { test } = require('uvu') +const { suite } = require('uvu') const assert = require('uvu/assert') -const MOCK_DB = require('../packages/database/src/mock') -const PROVIDER_DB = require('../packages/provider/src/mock') -const { - addKeyword, - createBot, - createFlow, - createProvider, -} = require('../packages/bot/index') +const { addKeyword, createBot, createFlow } = require('../packages/bot/index') +const { setup, clear, delay } = require('../__mocks__/env') -test(`[Caso - 03] Flow puro`, async () => { - const MOCK_VALUES = ['Bienvenido a mi tienda', 'Como estas?'] +const fakeHTTP = async (fakeData = []) => { + await delay(50) + const data = fakeData.map((u) => ({ body: `${u}` })) + return Promise.resolve(data) +} - const provider = createProvider(PROVIDER_DB) - const database = new MOCK_DB() +const suiteCase = suite('Flujo: flowDynamic') - const flujoPrincipal = addKeyword(['hola']) - .addAnswer(MOCK_VALUES[0]) - .addAnswer(MOCK_VALUES[1]) +suiteCase.before.each(setup) +suiteCase.after.each(clear) + +suiteCase(`Responder con mensajes asyncronos`, async ({ database, provider }) => { + const MOCK_VALUES = [ + 'Bienvenido te envio muchas marcas (5510)', + 'Seleccione marca del auto a cotizar, con el *número* correspondiente', + 'Seleccione la sub marca del auto a cotizar, con el *número* correspondiente:', + 'Los precios rondan:', + ] + const flow = addKeyword(['hola']) + .addAnswer(MOCK_VALUES[0], null, async (_, { flowDynamic }) => { + const data = await fakeHTTP(['Ford', 'GM', 'BMW']) + return flowDynamic(data) + }) + .addAnswer(MOCK_VALUES[1], null, async (_, { flowDynamic }) => { + const data = await fakeHTTP(['Ranger', 'Explorer']) + return flowDynamic(data) + }) + .addAnswer(MOCK_VALUES[2], null, async (_, { flowDynamic }) => { + const data = await fakeHTTP(['Usado', 'Nuevos']) + return flowDynamic(data) + }) + .addAnswer(MOCK_VALUES[3], null, async (_, { flowDynamic }) => { + const data = await fakeHTTP(['1000', '2000', '3000']) + return flowDynamic(data) + }) createBot({ database, - flow: createFlow([flujoPrincipal]), provider, + flow: createFlow([flow]), }) - provider.delaySendMessage(0, 'message', { + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + await delay(1200) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is(MOCK_VALUES[0], getHistory[0]) + + //FlowDynamic + assert.is('Ford', getHistory[1]) + assert.is('GM', getHistory[2]) + assert.is('BMW', getHistory[3]) + + assert.is(MOCK_VALUES[1], getHistory[4]) + + //FlowDynamic + assert.is('Ranger', getHistory[5]) + assert.is('Explorer', getHistory[6]) + + assert.is(MOCK_VALUES[2], getHistory[7]) + + //FlowDynamic + assert.is('Usado', getHistory[8]) + assert.is('Nuevos', getHistory[9]) + + assert.is(MOCK_VALUES[3], getHistory[10]) + + //FlowDynamic + assert.is('1000', getHistory[11]) + assert.is('2000', getHistory[12]) + assert.is('3000', getHistory[13]) + assert.is(undefined, getHistory[14]) +}) + +suiteCase(`Responder con un "string"`, async ({ database, provider }) => { + const flow = addKeyword(['hola']) + .addAnswer('Como vas?', null, async (_, { flowDynamic }) => { + return flowDynamic('Todo bien!') + }) + .addAnswer('y vos?') + + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { from: '000', body: 'hola', }) await delay(10) const getHistory = database.listHistory.map((i) => i.answer) - - assert.is(MOCK_VALUES[0], getHistory[0]) - assert.is(MOCK_VALUES[1], getHistory[1]) + assert.is('Como vas?', getHistory[0]) + assert.is('Todo bien!', getHistory[1]) + assert.is('y vos?', getHistory[2]) + assert.is(undefined, getHistory[3]) }) -test.run() +suiteCase(`Responder con un "array"`, async ({ database, provider }) => { + const flow = addKeyword(['hola']) + .addAnswer('Como vas?', null, async (_, { flowDynamic }) => { + return flowDynamic(['Todo bien!', 'trabajando']) + }) + .addAnswer('y vos?') -function delay(ms) { - return new Promise((res) => setTimeout(res, ms)) -} + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + await delay(10) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is('Como vas?', getHistory[0]) + assert.is('Todo bien!', getHistory[1]) + assert.is('trabajando', getHistory[2]) + assert.is('y vos?', getHistory[3]) + assert.is(undefined, getHistory[4]) +}) + +suiteCase(`Responder con un "object"`, async ({ database, provider }) => { + const flow = addKeyword(['hola']) + .addAnswer('Como vas?', null, async (_, { flowDynamic }) => { + return flowDynamic([{ body: 'Todo bien!' }]) + }) + .addAnswer('y vos?') + + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + await delay(10) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is('Como vas?', getHistory[0]) + assert.is('Todo bien!', getHistory[1]) + assert.is('y vos?', getHistory[2]) + assert.is(undefined, getHistory[3]) +}) + +suiteCase.run() diff --git a/__test__/04-case.test.js b/__test__/04-case.test.js index 2291a0c..f2280bb 100644 --- a/__test__/04-case.test.js +++ b/__test__/04-case.test.js @@ -1,82 +1,167 @@ -const { test } = require('uvu') +const { suite } = require('uvu') const assert = require('uvu/assert') -const MOCK_DB = require('../packages/database/src/mock') -const PROVIDER_DB = require('../packages/provider/src/mock') -const { - addKeyword, - createBot, - createFlow, - createProvider, -} = require('../packages/bot/index') +const { addKeyword, createBot, createFlow } = require('../packages/bot/index') +const { setup, clear, delay } = require('../__mocks__/env') -/** - * Falsear peticion async - * @param {*} fakeData - * @returns - */ const fakeHTTP = async (fakeData = []) => { - console.log('⚡ Server request!') await delay(50) - console.log('⚡ Server return!') - const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` })) - console.log(data) + const data = fakeData.map((u) => ({ body: `${u}` })) return Promise.resolve(data) } -test(`[Caso - 04] Romper flujo (endFlow)`, async () => { +const suiteCase = suite('Flujo: endFlow') + +suiteCase.before.each(setup) +suiteCase.after.each(clear) + +suiteCase(`Detener el flujo`, async ({ database, provider }) => { const MOCK_VALUES = [ - 'Bienvenido te envio muchas marcas (5510)', + 'Bienvenido te envio muchas marcas', 'Seleccione marca del auto a cotizar, con el *número* correspondiente', 'Seleccione la sub marca del auto a cotizar, con el *número* correspondiente:', 'Los precios rondan:', ] - const provider = createProvider(PROVIDER_DB) - const database = new MOCK_DB() - - const flujoPrincipal = addKeyword(['hola']) - .addAnswer(MOCK_VALUES[0], null, async (ctx, { flowDynamic }) => { - console.log('execute...') + const flow = addKeyword(['hola']) + .addAnswer(MOCK_VALUES[0], null, async (_, { flowDynamic }) => { const data = await fakeHTTP(['Ford', 'GM', 'BMW']) return flowDynamic(data) }) - .addAnswer(MOCK_VALUES[1], null, async (ctx, { endFlow }) => { + .addAnswer(MOCK_VALUES[1], null, async (_, { endFlow }) => { return endFlow() }) - .addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => { - const data = await fakeHTTP(['Usado', 'Nuevos']) - return flowDynamic(data) - }) - .addAnswer(MOCK_VALUES[3], null, async (ctx, { flowDynamic }) => { + .addAnswer(MOCK_VALUES[2]) + .addAnswer(MOCK_VALUES[3], null, async (_, { flowDynamic }) => { const data = await fakeHTTP(['1000', '2000', '3000']) return flowDynamic(data) }) createBot({ database, - flow: createFlow([flujoPrincipal]), provider, + flow: createFlow([flow]), }) - provider.delaySendMessage(0, 'message', { + await provider.delaySendMessage(0, 'message', { from: '000', body: 'hola', }) - await delay(1200) + await delay(500) const getHistory = database.listHistory.map((i) => i.answer) assert.is(MOCK_VALUES[0], getHistory[0]) //FlowDynamic - assert.is('1 Ford', getHistory[1]) - assert.is('2 GM', getHistory[2]) - assert.is('3 BMW', getHistory[3]) + assert.is('Ford', getHistory[1]) + assert.is('GM', getHistory[2]) + assert.is('BMW', getHistory[3]) assert.is(MOCK_VALUES[1], getHistory[4]) + + //FlowDynamic assert.is(undefined, getHistory[5]) + assert.is(undefined, getHistory[6]) }) -test.run() +suiteCase(`Detener el flujo flowDynamic`, async ({ database, provider }) => { + const flow = addKeyword(['hola']) + .addAnswer('Buenas!', null, async (_, { endFlow, flowDynamic }) => { + await flowDynamic('Continuamos...') + return endFlow() + }) + .addAnswer('Como estas!') -function delay(ms) { - return new Promise((res) => setTimeout(res, ms)) -} + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + await delay(10) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is('Buenas!', getHistory[0]) + assert.is('Continuamos...', getHistory[1]) + assert.is(undefined, getHistory[2]) +}) + +suiteCase(`flowDynamic con capture`, async ({ database, provider }) => { + const MOCK_VALUES = ['¿CUal es tu email?', 'Continuamos....', '¿Cual es tu edad?'] + + const flow = addKeyword(['hola']) + .addAnswer( + MOCK_VALUES[0], + { + capture: true, + }, + async (ctx, { flowDynamic, fallBack }) => { + const validation = ctx.body.includes('@') + + if (validation) { + const getDataFromApi = await fakeHTTP(['Gracias por tu email se ha validado de manera correcta']) + return flowDynamic(getDataFromApi) + } + return fallBack() + } + ) + .addAnswer(MOCK_VALUES[1]) + .addAnswer(MOCK_VALUES[2], { capture: true }, async (ctx, { flowDynamic, fallBack }) => { + if (ctx.body !== '18') { + await delay(20) + return fallBack('Ups creo que no eres mayor de edad') + } + return flowDynamic('Bien tu edad es correcta!') + }) + .addAnswer('Puedes pasar') + + createBot({ + database, + provider, + flow: createFlow([flow]), + }) + + await provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + await provider.delaySendMessage(10, 'message', { + from: '000', + body: 'this is not email value', + }) + + await provider.delaySendMessage(20, 'message', { + from: '000', + body: 'test@test.com', + }) + + await provider.delaySendMessage(90, 'message', { + from: '000', + body: '20', + }) + + await provider.delaySendMessage(200, 'message', { + from: '000', + body: '18', + }) + + await delay(500) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is(MOCK_VALUES[0], getHistory[0]) + assert.is('this is not email value', getHistory[1]) + assert.is(MOCK_VALUES[0], getHistory[2]) + assert.is('test@test.com', getHistory[3]) + assert.is('Gracias por tu email se ha validado de manera correcta', getHistory[4]) + assert.is(MOCK_VALUES[1], getHistory[5]) + assert.is(MOCK_VALUES[2], getHistory[6]) + assert.is('20', getHistory[7]) + assert.is('Ups creo que no eres mayor de edad', getHistory[8]) + assert.is('18', getHistory[9]) + assert.is('Bien tu edad es correcta!', getHistory[10]) + assert.is('Puedes pasar', getHistory[11]) +}) + +suiteCase.run() diff --git a/__test__/05-case.test.js b/__test__/05-case.test.js index 8e821f2..3962d31 100644 --- a/__test__/05-case.test.js +++ b/__test__/05-case.test.js @@ -1,24 +1,16 @@ -const { test } = require('uvu') +const { suite } = require('uvu') const assert = require('uvu/assert') -const MOCK_DB = require('../packages/database/src/mock') -const PROVIDER_DB = require('../packages/provider/src/mock') -const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index') +const { addKeyword, createBot, createFlow } = require('../packages/bot/index') +const { setup, clear, delay } = require('../__mocks__/env') -/** - * Falsear peticion async - * @param {*} fakeData - * @returns - */ -const fakeHTTP = async (fakeData = []) => { - await delay(5) - const data = fakeData.map((u, i) => ({ body: `${u}` })) - return Promise.resolve(data) -} +const suiteCase = suite('Flujo: manejo de estado') -test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { - const MOCK_VALUES = ['¿CUal es tu email?', 'Continuamos....', '¿Cual es tu edad?'] - const provider = createProvider(PROVIDER_DB) - const database = new MOCK_DB() +suiteCase.before.each(setup) +suiteCase.after.each(clear) + +suiteCase(`Debe retornar un mensaje resumen`, async ({ database, provider }) => { + let STATE_APP = {} + const MOCK_VALUES = ['¿Cual es tu nombre?', '¿Cual es tu edad?', 'Tu datos son:'] const flujoPrincipal = addKeyword(['hola']) .addAnswer( @@ -26,25 +18,27 @@ test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { { capture: true, }, - async (ctx, { flowDynamic, fallBack }) => { - const validation = ctx.body.includes('@') + async (ctx, { flowDynamic }) => { + STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], name: ctx.body } - if (validation) { - const getDataFromApi = await fakeHTTP(['Gracias por tu email se ha validado de manera correcta']) - return flowDynamic(getDataFromApi) - } - return fallBack() + flowDynamic('Gracias por tu nombre!') } ) - .addAnswer(MOCK_VALUES[1]) - .addAnswer(MOCK_VALUES[2], { capture: true }, async (ctx, { flowDynamic, fallBack }) => { - if (ctx.body !== '18') { - await delay(20) - return fallBack('Ups creo que no eres mayor de edad') + .addAnswer( + MOCK_VALUES[1], + { + capture: true, + }, + async (ctx, { flowDynamic }) => { + STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], age: ctx.body } + + await flowDynamic(`Gracias por tu edad! ${STATE_APP[ctx.from].name}`) } - return flowDynamic('Bien tu edad es correcta!') + ) + .addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => { + flowDynamic(`Nombre: ${STATE_APP[ctx.from].name} Edad: ${STATE_APP[ctx.from].age}`) }) - .addAnswer('Puedes pasar') + .addAnswer('🤖🤖 Gracias por tu participacion') createBot({ database, @@ -57,44 +51,47 @@ test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { body: 'hola', }) + provider.delaySendMessage(5, 'message', { + from: '001', + body: 'hola', + }) + provider.delaySendMessage(10, 'message', { from: '000', - body: 'this is not email value', + body: 'Leifer', + }) + + provider.delaySendMessage(15, 'message', { + from: '000', + body: '90', }) provider.delaySendMessage(20, 'message', { - from: '000', - body: 'test@test.com', + from: '001', + body: 'Maria', }) - provider.delaySendMessage(90, 'message', { - from: '000', - body: '20', + provider.delaySendMessage(25, 'message', { + from: '001', + body: '100', }) - provider.delaySendMessage(200, 'message', { - from: '000', - body: '18', - }) - - await delay(1200) + await delay(500) const getHistory = database.listHistory.map((i) => i.answer) assert.is(MOCK_VALUES[0], getHistory[0]) - assert.is('this is not email value', getHistory[1]) - assert.is(MOCK_VALUES[0], getHistory[2]) - assert.is('test@test.com', getHistory[3]) - assert.is('Gracias por tu email se ha validado de manera correcta', getHistory[4]) - assert.is(MOCK_VALUES[1], getHistory[5]) - assert.is(MOCK_VALUES[2], getHistory[6]) - assert.is('20', getHistory[7]) - assert.is('Ups creo que no eres mayor de edad', getHistory[8]) - assert.is('18', getHistory[9]) - assert.is('Bien tu edad es correcta!', getHistory[10]) - assert.is('Puedes pasar', getHistory[11]) + assert.is('¿Cual es tu nombre?', getHistory[1]) + assert.is('Leifer', getHistory[2]) + assert.is('Gracias por tu nombre!', getHistory[3]) + assert.is('¿Cual es tu edad?', getHistory[4]) + assert.is('90', getHistory[5]) + assert.is('Gracias por tu edad! Leifer', getHistory[6]) + assert.is('Tu datos son:', getHistory[7]) + assert.is('Nombre: Leifer Edad: 90', getHistory[8]) + assert.is('🤖🤖 Gracias por tu participacion', getHistory[9]) + assert.is('Maria', getHistory[10]) + assert.is('Gracias por tu nombre!', getHistory[11]) + assert.is('100', getHistory[12]) + assert.is(undefined, getHistory[13]) }) -test.run() - -function delay(ms) { - return new Promise((res) => setTimeout(res, ms)) -} +suiteCase.run() diff --git a/__test__/06-case.test.js b/__test__/06-case.test.js deleted file mode 100644 index c68679e..0000000 --- a/__test__/06-case.test.js +++ /dev/null @@ -1,111 +0,0 @@ -const { test } = require('uvu') -const assert = require('uvu/assert') -const MOCK_DB = require('../packages/database/src/mock') -const PROVIDER_DB = require('../packages/provider/src/mock') -const { - addKeyword, - createBot, - createFlow, - createProvider, -} = require('../packages/bot/index') - -/** - * Falsear peticion async - * @param {*} fakeData - * @returns - */ -const fakeHTTP = async (fakeData = []) => { - await delay(5) - const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` })) - return Promise.resolve(data) -} - -test(`[Caso - 06] Finalizar Flujo (endFlow)`, async () => { - const MOCK_VALUES = [ - '¿CUal es tu email?', - 'Continuamos....', - '¿Cual es tu edad?', - ] - const provider = createProvider(PROVIDER_DB) - const database = new MOCK_DB() - - const flujoPrincipal = addKeyword(['hola']) - .addAnswer( - MOCK_VALUES[0], - { - capture: true, - }, - async (ctx, { flowDynamic, fallBack }) => { - const validation = ctx.body.includes('@') - - if (validation) { - const getDataFromApi = await fakeHTTP([ - 'Gracias por tu email se ha validado de manera correcta', - ]) - return flowDynamic(getDataFromApi) - } - return fallBack(validation) - } - ) - .addAnswer(MOCK_VALUES[1], null, async (_, { endFlow }) => { - return endFlow() - }) - .addAnswer( - MOCK_VALUES[2], - { capture: true }, - async (ctx, { flowDynamic, fallBack }) => { - if (ctx.body !== '18') { - await delay(50) - return fallBack(false, 'Ups creo que no eres mayor de edad') - } - return flowDynamic('Bien tu edad es correcta!') - } - ) - .addAnswer('Puedes pasar') - - createBot({ - database, - flow: createFlow([flujoPrincipal]), - provider, - }) - - provider.delaySendMessage(0, 'message', { - from: '000', - body: 'hola', - }) - - provider.delaySendMessage(10, 'message', { - from: '000', - body: 'this is not email value', - }) - - provider.delaySendMessage(20, 'message', { - from: '000', - body: 'test@test.com', - }) - - provider.delaySendMessage(90, 'message', { - from: '000', - body: '20', - }) - - await delay(1200) - const getHistory = database.listHistory.map((i) => i.answer) - assert.is(MOCK_VALUES[0], getHistory[0]) - assert.is('this is not email value', getHistory[1]) - assert.is(MOCK_VALUES[0], getHistory[2]) - assert.is('test@test.com', getHistory[3]) - assert.is( - '1 Gracias por tu email se ha validado de manera correcta', - getHistory[4] - ) - assert.is(MOCK_VALUES[1], getHistory[5]) - assert.is('20', getHistory[6]) - assert.is(undefined, getHistory[7]) -}) - -test.run() - -function delay(ms) { - return new Promise((res) => setTimeout(res, ms)) -} diff --git a/__test__/07-case.test.js b/__test__/07-case.test.js deleted file mode 100644 index efe2ed5..0000000 --- a/__test__/07-case.test.js +++ /dev/null @@ -1,81 +0,0 @@ -const { test } = require('uvu') -const assert = require('uvu/assert') -const MOCK_DB = require('../packages/database/src/mock') -const PROVIDER_DB = require('../packages/provider/src/mock') -const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index') - -let STATE_APP = {} - -test(`[Caso - 07] Retornar estado`, async () => { - const MOCK_VALUES = ['¿Cual es tu nombre?', '¿Cual es tu edad?', 'Tu datos son:'] - const provider = createProvider(PROVIDER_DB) - const database = new MOCK_DB() - - const flujoPrincipal = addKeyword(['hola']) - .addAnswer( - MOCK_VALUES[0], - { - capture: true, - }, - async (ctx, { flowDynamic, fallBack }) => { - STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], name: ctx.body } - - flowDynamic('Gracias por tu nombre!') - } - ) - .addAnswer( - MOCK_VALUES[1], - { - capture: true, - }, - async (ctx, { flowDynamic, endFlow }) => { - STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], age: ctx.body } - - await flowDynamic('Gracias por tu edad!') - } - ) - .addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => { - flowDynamic(`Nombre: ${STATE_APP[ctx.from].name} Edad: ${STATE_APP[ctx.from].age}`) - }) - .addAnswer('🤖🤖 Gracias por tu participacion') - - createBot({ - database, - flow: createFlow([flujoPrincipal]), - provider, - }) - - provider.delaySendMessage(0, 'message', { - from: '000', - body: 'hola', - }) - - provider.delaySendMessage(20, 'message', { - from: '000', - body: 'Leifer', - }) - - provider.delaySendMessage(40, 'message', { - from: '000', - body: '90', - }) - - await delay(1200) - const getHistory = database.listHistory.map((i) => i.answer) - assert.is(MOCK_VALUES[0], getHistory[0]) - assert.is('Leifer', getHistory[1]) - assert.is('Gracias por tu nombre!', getHistory[2]) - assert.is('¿Cual es tu edad?', getHistory[3]) - assert.is('90', getHistory[4]) - assert.is('Gracias por tu edad!', getHistory[5]) - assert.is('Tu datos son:', getHistory[6]) - assert.is('Nombre: Leifer Edad: 90', getHistory[7]) - assert.is('🤖🤖 Gracias por tu participacion', getHistory[8]) - assert.is(undefined, getHistory[9]) -}) - -test.run() - -function delay(ms) { - return new Promise((res) => setTimeout(res, ms)) -} diff --git a/__test__/08-case.test.js b/__test__/08-case.test.js deleted file mode 100644 index ac295d1..0000000 --- a/__test__/08-case.test.js +++ /dev/null @@ -1,44 +0,0 @@ -// const { test } = require('uvu') -// const assert = require('uvu/assert') -// const MOCK_DB = require('../packages/database/src/mock') -// const PROVIDER_DB = require('../packages/provider/src/mock') -// const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index') - -// const database = new MOCK_DB() -// test.before(() => { -// database.listHistory = [] -// }); -// test.after(() => { -// database.listHistory = [] -// }); - -// test(`[Caso - 08] Regular expression on keyword`, async () => { -// const provider = createProvider(PROVIDER_DB) - -// const REGEX_CREDIT_NUMBER = `/(^4[0-9]{12}(?:[0-9]{3})?$)|(^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$)|(3[47][0-9]{13})|(^3(?:0[0-5]|[68][0-9])[0-9]{11}$)|(^6(?:011|5[0-9]{2})[0-9]{12}$)|(^(?:2131|1800|35\d{3})\d{11}$)/gm` -// const flujoPrincipal = addKeyword(REGEX_CREDIT_NUMBER, { regex: true }) -// .addAnswer(`Gracias por proporcionar un numero de tarjeta valido`) -// .addAnswer('Fin!') - -// createBot({ -// database, -// flow: createFlow([flujoPrincipal]), -// provider, -// }) - -// provider.delaySendMessage(0, 'message', { -// from: '000', -// body: '374245455400126', -// }) - -// const getHistory = database.listHistory.map((i) => i.answer) -// assert.is('Gracias por proporcionar un numero de tarjeta valido', getHistory[1]) -// assert.is('Leifer', getHistory[1]) - -// }) - -// test.run() - -// function delay(ms) { -// return new Promise((res) => setTimeout(res, ms)) -// } diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index dbb84a2..ed91755 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -139,7 +139,7 @@ class CoreClass { const continueFlow = async () => { const currentPrev = await this.databaseClass.getPrevByNumber(from) - const nextFlow = await this.flowClass.find(refToContinue?.ref, true) + const nextFlow = (await this.flowClass.find(refToContinue?.ref, true)) ?? [] const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize) const isContinueFlow = filterNextFlow.map((i) => i.keyword).includes(currentPrev?.ref) if (!isContinueFlow) await sendFlow(filterNextFlow, from, { prev: undefined }) diff --git a/packages/bot/io/flow.class.js b/packages/bot/io/flow.class.js index 13de732..c7cf1e9 100644 --- a/packages/bot/io/flow.class.js +++ b/packages/bot/io/flow.class.js @@ -25,16 +25,8 @@ class FlowClass { let refSymbol = null overFlow = overFlow ?? this.flowSerialize - const customRegex = (str = null) => { - if (typeof str !== 'string') return - const instanceRegex = new RegExp(str) - return instanceRegex.test(str) - } - - /** Retornar expresion regular para buscar coincidencia */ const mapSensitive = (str, mapOptions = { sensitive: false, regex: false }) => { - if (mapOptions.regex) return customRegex(str) - + if (mapOptions.regex) return new RegExp(str) const regexSensitive = mapOptions.sensitive ? 'g' : 'i' if (Array.isArray(str)) { return new RegExp(str.join('|'), regexSensitive) @@ -43,10 +35,7 @@ class FlowClass { } const findIn = (keyOrWord, symbol = false, flow = overFlow) => { - const sensitive = refSymbol?.options?.sensitive || false - const regex = refSymbol?.options?.regex || false capture = refSymbol?.options?.capture || false - if (capture) return messages if (symbol) { @@ -55,6 +44,8 @@ class FlowClass { if (refSymbol?.ref) findIn(refSymbol.ref, true) } else { refSymbol = flow.find((c) => { + const sensitive = c?.options?.sensitive || false + const regex = c?.options?.regex || false return mapSensitive(c.keyword, { sensitive, regex }).test(keyOrWord) }) if (refSymbol?.ref) findIn(refSymbol.ref, true) diff --git a/packages/provider/src/mock/index.js b/packages/provider/src/mock/index.js index 63034c0..9f47757 100644 --- a/packages/provider/src/mock/index.js +++ b/packages/provider/src/mock/index.js @@ -1,20 +1,20 @@ -const { ProviderClass } = require('@bot-whatsapp/bot') +const { ProviderClass } = require('../../../bot') + +function delay(ms) { + return new Promise((res) => setTimeout(res, ms)) +} class MockProvider extends ProviderClass { constructor() { super() } - delaySendMessage = (miliseconds, eventName, payload) => - new Promise((res) => - setTimeout(() => { - this.emit(eventName, payload) - res - }, miliseconds) - ) + delaySendMessage = async (miliseconds, eventName, payload) => { + await delay(miliseconds) + this.emit(eventName, payload) + } sendMessage = async (userId, message) => { - console.log(`Enviando... ${userId}, ${message}`) return Promise.resolve({ userId, message }) } }