mirror of
https://github.com/cheveguerra/bot-whatsapp.git
synced 2026-04-20 12:39:24 +00:00
perf(adapter): 🐛 database json and lot tests
perf(adapter): 🐛 database json and lot tests
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,6 +36,7 @@ tmp/
|
|||||||
.fleet/
|
.fleet/
|
||||||
example-app*/
|
example-app*/
|
||||||
base-*/
|
base-*/
|
||||||
|
test-*.json
|
||||||
!starters/apps/base-*/
|
!starters/apps/base-*/
|
||||||
qr.svg
|
qr.svg
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const MOCK_DB = require('../packages/database/src/mock')
|
const MOCK_DB = require('../packages/database/src/json')
|
||||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||||
|
|
||||||
class MOCK_FLOW {
|
class MOCK_FLOW {
|
||||||
@@ -16,14 +16,25 @@ class MOCK_FLOW {
|
|||||||
findIndexByRef = () => 0
|
findIndexByRef = () => 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cleaName = (name) => {
|
||||||
|
name = name.toLowerCase()
|
||||||
|
name = name.replaceAll(' ', '-')
|
||||||
|
name = name.replaceAll(':', '-')
|
||||||
|
name = name.replaceAll('"', '-')
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preparar env para el test
|
* Preparar env para el test
|
||||||
* @param {*} context
|
* @param {*} context
|
||||||
*/
|
*/
|
||||||
const setup = async (context) => {
|
const setup = async (context) => {
|
||||||
|
const name = cleaName(`${context.__suite__}-${context.__test__}`)
|
||||||
|
const filename = `test-${name}.json`
|
||||||
context.provider = new PROVIDER_DB()
|
context.provider = new PROVIDER_DB()
|
||||||
context.database = new MOCK_DB()
|
context.database = new MOCK_DB({ filename })
|
||||||
context.flow = new MOCK_FLOW()
|
context.flow = new MOCK_FLOW()
|
||||||
|
await delay(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
const clear = async (context) => {
|
const clear = async (context) => {
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ suiteCase(`Responder a "hola"`, async ({ database, provider }) => {
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(0)
|
await delay(10)
|
||||||
|
|
||||||
assert.is('Buenas!', database.listHistory[0].answer)
|
assert.is('Buenas!', database.listHistory[0].answer)
|
||||||
assert.is('Como vamos!', database.listHistory[1].answer)
|
assert.is('Como vamos!', database.listHistory[1].answer)
|
||||||
assert.is(undefined, database.listHistory[2])
|
assert.is(undefined, database.listHistory[2])
|
||||||
@@ -43,7 +42,7 @@ suiteCase(`NO reponder a "pepe"`, async ({ database, provider }) => {
|
|||||||
body: 'pepe',
|
body: 'pepe',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(0)
|
await delay(100)
|
||||||
|
|
||||||
assert.is(undefined, database.listHistory[0])
|
assert.is(undefined, database.listHistory[0])
|
||||||
assert.is(undefined, database.listHistory[1])
|
assert.is(undefined, database.listHistory[1])
|
||||||
|
|||||||
31
__test__/0.0.1-case.test.js
Normal file
31
__test__/0.0.1-case.test.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
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: Provider envia un location')
|
||||||
|
|
||||||
|
suiteCase.before.each(setup)
|
||||||
|
suiteCase.after.each(clear)
|
||||||
|
|
||||||
|
suiteCase(`Responder a "CURRENT_LOCATION"`, async ({ database, provider }) => {
|
||||||
|
const flow = addKeyword('#CURRENT_LOCATION#').addAnswer('Gracias por tu location')
|
||||||
|
|
||||||
|
createBot({
|
||||||
|
database,
|
||||||
|
provider,
|
||||||
|
flow: createFlow([flow]),
|
||||||
|
})
|
||||||
|
|
||||||
|
await provider.delaySendMessage(0, 'message', {
|
||||||
|
from: '000',
|
||||||
|
body: '#CURRENT_LOCATION#',
|
||||||
|
})
|
||||||
|
|
||||||
|
await delay(200)
|
||||||
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
|
assert.is('Gracias por tu location', getHistory[0])
|
||||||
|
assert.is(undefined, getHistory[1])
|
||||||
|
})
|
||||||
|
|
||||||
|
suiteCase.run()
|
||||||
@@ -22,7 +22,7 @@ suiteCase(`Responder a "ole" en minuscula`, async ({ database, provider }) => {
|
|||||||
body: 'ole',
|
body: 'ole',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(0)
|
await delay(100)
|
||||||
|
|
||||||
assert.is('Bienvenido a la OLA', database.listHistory[0].answer)
|
assert.is('Bienvenido a la OLA', database.listHistory[0].answer)
|
||||||
assert.is(undefined, database.listHistory[1])
|
assert.is(undefined, database.listHistory[1])
|
||||||
@@ -42,7 +42,7 @@ suiteCase(`NO Responder a "ole" en minuscula`, async ({ database, provider }) =>
|
|||||||
body: 'OLE',
|
body: 'OLE',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(0)
|
await delay(100)
|
||||||
|
|
||||||
assert.is(undefined, database.listHistory[0])
|
assert.is(undefined, database.listHistory[0])
|
||||||
assert.is(undefined, database.listHistory[1])
|
assert.is(undefined, database.listHistory[1])
|
||||||
|
|||||||
@@ -51,22 +51,22 @@ suiteCase(`Debe continuar el flujo del hijo`, async ({ database, provider }) =>
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await provider.delaySendMessage(10, 'message', {
|
await provider.delaySendMessage(30, 'message', {
|
||||||
from: '000',
|
from: '000',
|
||||||
body: 'test@test.com',
|
body: 'test@test.com',
|
||||||
})
|
})
|
||||||
|
|
||||||
await provider.delaySendMessage(15, 'message', {
|
await provider.delaySendMessage(60, 'message', {
|
||||||
from: '000',
|
from: '000',
|
||||||
body: 'paypal',
|
body: 'paypal',
|
||||||
})
|
})
|
||||||
|
|
||||||
await provider.delaySendMessage(20, 'message', {
|
await provider.delaySendMessage(90, 'message', {
|
||||||
from: '000',
|
from: '000',
|
||||||
body: 'continue!',
|
body: 'continue!',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(500)
|
await delay(800)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
|
|
||||||
assert.is('¿Como estas todo bien?', getHistory[0])
|
assert.is('¿Como estas todo bien?', getHistory[0])
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ suiteCase(`Responder a una expresion regular`, async ({ database, provider }) =>
|
|||||||
body: '374245455400126',
|
body: '374245455400126',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(10)
|
await delay(100)
|
||||||
|
|
||||||
assert.is('Gracias por proporcionar un numero de tarjeta valido', database.listHistory[0].answer)
|
assert.is('Gracias por proporcionar un numero de tarjeta valido', database.listHistory[0].answer)
|
||||||
assert.is('Fin!', database.listHistory[1].answer)
|
assert.is('Fin!', database.listHistory[1].answer)
|
||||||
@@ -50,7 +50,7 @@ suiteCase(`NO Responder a una expresion regular`, async ({ database, provider })
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(10)
|
await delay(100)
|
||||||
|
|
||||||
assert.is(undefined, database.listHistory[0])
|
assert.is(undefined, database.listHistory[0])
|
||||||
assert.is(undefined, database.listHistory[1])
|
assert.is(undefined, database.listHistory[1])
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ suiteCase(`Responder a "pregunta"`, async ({ database, provider }) => {
|
|||||||
body: '90',
|
body: '90',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(20)
|
await delay(100)
|
||||||
|
|
||||||
assert.is(['Hola como estas?', '¿Cual es tu edad?'].join('\n'), database.listHistory[0].answer)
|
assert.is(['Hola como estas?', '¿Cual es tu edad?'].join('\n'), database.listHistory[0].answer)
|
||||||
assert.is('90', database.listHistory[1].answer)
|
assert.is('90', database.listHistory[1].answer)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ suiteCase(`Responder con mensajes asyncronos`, async ({ database, provider }) =>
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(1200)
|
await delay(1500)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ suiteCase(`Responder con un "string"`, async ({ database, provider }) => {
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(10)
|
await delay(100)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is('Como vas?', getHistory[0])
|
assert.is('Como vas?', getHistory[0])
|
||||||
assert.is('Todo bien!', getHistory[1])
|
assert.is('Todo bien!', getHistory[1])
|
||||||
@@ -124,7 +124,7 @@ suiteCase(`Responder con un "array"`, async ({ database, provider }) => {
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(10)
|
await delay(100)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is('Como vas?', getHistory[0])
|
assert.is('Como vas?', getHistory[0])
|
||||||
assert.is('Todo bien!', getHistory[1])
|
assert.is('Todo bien!', getHistory[1])
|
||||||
@@ -151,7 +151,7 @@ suiteCase(`Responder con un "object"`, async ({ database, provider }) => {
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(10)
|
await delay(100)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is('Como vas?', getHistory[0])
|
assert.is('Como vas?', getHistory[0])
|
||||||
assert.is('Todo bien!', getHistory[1])
|
assert.is('Todo bien!', getHistory[1])
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ suiteCase(`Detener el flujo`, async ({ database, provider }) => {
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(500)
|
await delay(900)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ suiteCase(`Detener el flujo flowDynamic`, async ({ database, provider }) => {
|
|||||||
body: 'hola',
|
body: 'hola',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(10)
|
await delay(100)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is('Buenas!', getHistory[0])
|
assert.is('Buenas!', getHistory[0])
|
||||||
assert.is('Continuamos...', getHistory[1])
|
assert.is('Continuamos...', getHistory[1])
|
||||||
@@ -148,7 +148,7 @@ suiteCase(`flowDynamic con capture`, async ({ database, provider }) => {
|
|||||||
body: '18',
|
body: '18',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(500)
|
await delay(900)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||||
assert.is('this is not email value', getHistory[1])
|
assert.is('this is not email value', getHistory[1])
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ suiteCase(`Debe retornar un mensaje resumen`, async ({ database, provider }) =>
|
|||||||
body: '100',
|
body: '100',
|
||||||
})
|
})
|
||||||
|
|
||||||
await delay(500)
|
await delay(1000)
|
||||||
const getHistory = database.listHistory.map((i) => i.answer)
|
const getHistory = database.listHistory.map((i) => i.answer)
|
||||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||||
assert.is('¿Cual es tu nombre?', getHistory[1])
|
assert.is('¿Cual es tu nombre?', getHistory[1])
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class CoreClass {
|
|||||||
from,
|
from,
|
||||||
prevRef: prevMsg.refSerialize,
|
prevRef: prevMsg.refSerialize,
|
||||||
})
|
})
|
||||||
this.databaseClass.save(ctxByNumber)
|
await this.databaseClass.save(ctxByNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 📄 Crar CTX de mensaje (uso private)
|
// 📄 Crar CTX de mensaje (uso private)
|
||||||
|
|||||||
@@ -1,63 +1,79 @@
|
|||||||
const { join } = require('path')
|
const { join } = require('path')
|
||||||
const { existsSync, writeFileSync, readFileSync } = require('fs')
|
const { existsSync } = require('fs')
|
||||||
|
const { writeFile, readFile } = require('fs').promises
|
||||||
|
|
||||||
class JsonFileAdapter {
|
class JsonFileAdapter {
|
||||||
db
|
db
|
||||||
pathFile
|
pathFile
|
||||||
listHistory = []
|
listHistory = []
|
||||||
|
options = { filename: 'db.json' }
|
||||||
|
|
||||||
constructor() {
|
constructor(options = {}) {
|
||||||
this.pathFile = join(process.cwd(), 'db.json')
|
this.options = { ...this.options, ...options }
|
||||||
|
this.pathFile = join(process.cwd(), this.options.filename)
|
||||||
this.init().then()
|
this.init().then()
|
||||||
}
|
}
|
||||||
|
|
||||||
databaseExists() {
|
/**
|
||||||
return existsSync(this.pathFile)
|
* Revisamos si existe o no el json file
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
init = async () => {
|
||||||
|
if (existsSync(this.pathFile)) {
|
||||||
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
async init() {
|
const parseData = JSON.stringify([], null, 2)
|
||||||
const dbExists = await this.databaseExists()
|
return writeFile(this.pathFile, parseData, 'utf-8')
|
||||||
|
} catch (e) {
|
||||||
if (!dbExists) {
|
return Promise.reject(e.message)
|
||||||
const data = {
|
|
||||||
history: [],
|
|
||||||
}
|
|
||||||
await this.saveData(data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readDatabase() {
|
validateJson = (raw) => {
|
||||||
const db = readFileSync(this.pathFile)
|
try {
|
||||||
return JSON.parse(db)
|
return JSON.parse(raw)
|
||||||
|
} catch (e) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveData(data) {
|
/**
|
||||||
writeFileSync(this.pathFile, JSON.stringify(data, null, 2))
|
* Leer archivo y parsear
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
readFileAndParse = async () => {
|
||||||
|
const data = await readFile(this.pathFile, 'utf-8')
|
||||||
|
const parseData = this.validateJson(data)
|
||||||
|
return parseData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buscamos el ultimo mensaje por numero
|
||||||
|
* @param {*} from
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
getPrevByNumber = async (from) => {
|
getPrevByNumber = async (from) => {
|
||||||
const { history } = await this.readDatabase()
|
const history = await this.readFileAndParse()
|
||||||
|
|
||||||
if (!history.length) {
|
if (!history.length) {
|
||||||
return null
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = history.filter((res) => res.from === from).pop()
|
const result = history
|
||||||
|
.slice()
|
||||||
return {
|
.reverse()
|
||||||
...result,
|
.filter((i) => !!i.keyword)
|
||||||
}
|
return result.find((a) => a.from === from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guardar dato
|
||||||
|
* @param {*} ctx
|
||||||
|
*/
|
||||||
save = async (ctx) => {
|
save = async (ctx) => {
|
||||||
this.db = await this.readDatabase()
|
|
||||||
|
|
||||||
this.db.history.push(ctx)
|
|
||||||
|
|
||||||
await this.saveData(this.db)
|
|
||||||
|
|
||||||
this.listHistory.push(ctx)
|
this.listHistory.push(ctx)
|
||||||
console.log('Guardado en DB...', ctx)
|
const parseData = JSON.stringify(this.listHistory, null, 2)
|
||||||
|
await writeFile(this.pathFile, parseData, 'utf-8')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class BaileysProvider extends ProviderClass {
|
|||||||
if (messageCtx.message.locationMessage) {
|
if (messageCtx.message.locationMessage) {
|
||||||
const { degreesLatitude, degreesLongitude } = messageCtx.message.locationMessage
|
const { degreesLatitude, degreesLongitude } = messageCtx.message.locationMessage
|
||||||
if (typeof degreesLatitude === 'number' && typeof degreesLongitude === 'number') {
|
if (typeof degreesLatitude === 'number' && typeof degreesLongitude === 'number') {
|
||||||
payload = { ...payload, body: `📍` }
|
payload = { ...payload, body: `#CURRENT_LOCATION#` }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class VenomProvider extends ProviderClass {
|
|||||||
const lat = payload.lat
|
const lat = payload.lat
|
||||||
const lng = payload.lng
|
const lng = payload.lng
|
||||||
if (lat !== '' && lng !== '') {
|
if (lat !== '' && lng !== '') {
|
||||||
payload = { ...payload, body: `📍` }
|
payload = { ...payload, body: `#CURRENT_LOCATION#` }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.emit('message', payload)
|
this.emit('message', payload)
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class WebWhatsappProvider extends ProviderClass {
|
|||||||
}
|
}
|
||||||
payload.from = wwebCleanNumber(payload.from, true)
|
payload.from = wwebCleanNumber(payload.from, true)
|
||||||
if (payload._data.lat && payload._data.lng) {
|
if (payload._data.lat && payload._data.lng) {
|
||||||
payload = { ...payload, body: `📍` }
|
payload = { ...payload, body: `#CURRENT_LOCATION#` }
|
||||||
}
|
}
|
||||||
this.emit('message', payload)
|
this.emit('message', payload)
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user