trysoftwacloudapi
Version:
TrySoft Whatsapp Cloud Api Wrapper
496 lines • 18.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const supertest_1 = __importDefault(require("supertest"));
const _1 = require(".");
const pubSub_1 = require("./utils/pubSub");
const expectSendMessageResult = (result) => {
expect(result && typeof result === 'object').toBe(true);
expect(result).toHaveProperty('messageId');
expect(result).toHaveProperty('phoneNumber');
expect(result).toHaveProperty('whatsappId');
expect(typeof result.messageId).toBe('string');
expect(typeof result.phoneNumber).toBe('string');
expect(typeof result.whatsappId).toBe('string');
};
const getRandomInt = (_min, _max) => {
const min = Math.ceil(_min);
const max = Math.floor(_max);
return Math.floor(Math.random() * (max - min + 1)) + min;
};
const fromPhoneNumberId = process.env.FROM_PHONE_NUMBER_ID;
const accessToken = process.env.ACCESS_TOKEN;
const version = process.env.VERSION;
const to = process.env.TO;
const webhookVerifyToken = process.env.WEBHOOK_VERIFY_TOKEN;
const webhookPath = process.env.WEBHOOK_PATH;
if (!fromPhoneNumberId || !accessToken || !to || !webhookVerifyToken || !webhookPath) {
throw new Error('Missing env variables');
}
describe('send functions', () => {
const bot = (0, _1.createBot)(fromPhoneNumberId, accessToken, { version });
test('sends text', async () => {
const result = await bot.sendText(to, 'Hello world', {
preview_url: true,
});
expectSendMessageResult(result);
});
test('sends message', async () => {
const result = await bot.sendMessage(to, 'Hello world', {
preview_url: true,
});
expectSendMessageResult(result);
});
test('sends image', async () => {
const result = await bot.sendImage(to, 'https://picsum.photos/200/300', {
caption: 'Random jpg',
});
expectSendMessageResult(result);
});
test('sends document', async () => {
const result = await bot.sendDocument(to, 'http://www.africau.edu/images/default/sample.pdf', {
caption: 'Random pdf',
filename: 'myfile.pdf',
});
expectSendMessageResult(result);
});
test('sends audio', async () => {
const result = await bot.sendAudio(to, 'https://samplelib.com/lib/preview/mp3/sample-3s.mp3');
expectSendMessageResult(result);
});
test('sends video', async () => {
const result = await bot.sendVideo(to, 'https://samplelib.com/lib/preview/mp4/sample-5s.mp4', {
caption: 'Random mp4',
});
expectSendMessageResult(result);
});
test('sends sticker', async () => {
const result = await bot.sendSticker(to, 'https://i.gifer.com/ZXHC.gif');
expectSendMessageResult(result);
});
test('sends location', async () => {
const result = await bot.sendLocation(to, 40.7128, -74.0060, {
name: 'New York',
});
expectSendMessageResult(result);
});
test('sends template', async () => {
const result = await bot.sendTemplate(to, 'hello_world', 'en_us');
expectSendMessageResult(result);
});
test('sends contacts', async () => {
const result = await bot.sendContacts(to, [{
name: {
formatted_name: 'John Doe',
first_name: 'John',
},
phones: [{
type: 'HOME',
phone: '0712345678',
}],
emails: [{
type: 'HOME',
email: 'random@random.com',
}],
}]);
expectSendMessageResult(result);
});
test('sends reply button', async () => {
const result = await bot.sendReplyButtons(to, 'Random body text', {
random_id_1: 'Button 1',
random_id_2: 'Button 2',
}, {
footerText: 'Random footer text',
header: {
type: 'text',
text: 'Random header text',
},
});
expectSendMessageResult(result);
});
test('sends list', async () => {
const result = await bot.sendList(to, 'Click me', 'Random body text', {
'Section 1': [
{
id: 'random_id_1',
title: 'Item 1',
description: 'Random description',
},
{
id: 'random_id_2',
title: 'Item 2',
},
],
'Section 2': [
{
id: 'random_id_3',
title: 'Item 3',
},
{
id: 'random_id_4',
title: 'Item 4',
description: 'Random description',
},
],
}, {
footerText: 'Random footer text',
header: {
type: 'text',
text: 'Random header text',
},
});
expectSendMessageResult(result);
});
});
describe('server functions', () => {
const bot = (0, _1.createBot)(fromPhoneNumberId, accessToken, { version });
let server;
let app;
beforeAll(async () => {
({ server, app } = await bot.startExpressServer({ webhookVerifyToken }));
});
afterAll(() => new Promise((resolve) => {
if (!server) {
resolve();
return;
}
server.close(() => {
console.log('✔️ Server closed');
resolve();
});
}));
test('invalid webhook token', async () => {
const sendRequest = (path) => (0, supertest_1.default)(app)
.get(path)
.send()
.expect(200);
const paths = [
webhookPath,
`${webhookPath}?hub.mode=subscribe&hub.challenge=random`,
`${webhookPath}?hub.mode=subscribe&hub.verify_token=abcd`,
`${webhookPath}?hub.mode=sub&hub.verify_token=abcd&hub.challenge=random`,
`${webhookPath}?hub.mode=subscribe&hub.verify_token=abcd&hub.challenge=random`,
];
for (let i = 0; i < paths.length; i += 1) {
await expect(sendRequest(paths[i])).rejects.toThrow();
}
});
test('verify webhook token', async () => {
const challenge = 'random';
const { text } = await (0, supertest_1.default)(app)
.get(`${webhookPath}?hub.mode=subscribe&hub.verify_token=${encodeURIComponent(webhookVerifyToken)}&hub.challenge=${challenge}`)
.send()
.expect(200);
expect(text).toBe(challenge);
});
test('send invalid body', async () => {
const sendRequest = (data) => (0, supertest_1.default)(app)
.post(webhookPath)
.send(data)
.expect(200);
const data = [
{},
{ object: 'abcd' },
{ entry: [] },
{ object: 'abcd', entry: [{ changes: [] }] },
{ object: 'abcd', entry: [{ changes: [{ value: { statuses: [] } }] }] },
];
for (let i = 0; i < data.length; i += 1) {
await expect(sendRequest(data[i])).rejects.toThrow();
}
});
test('listen for new messages', () => new Promise(async (resolve, reject) => {
const payloads = [
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'text',
text: { body: 'Hello' },
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'image',
image: {
mime_type: 'image/jpeg',
sha256: 'abcd=',
id: '1234',
},
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'document',
document: {
caption: 'Random pdf',
filename: 'myfile.pdf',
mime_type: 'application/pdf',
sha256: 'abcd=',
id: '1234',
},
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'audio',
audio: {
mime_type: 'audio/mpeg',
sha256: 'abcd=',
id: '1234',
voice: false,
},
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'video',
video: {
mime_type: 'video/mp4',
sha256: 'abcd=',
id: '1234',
},
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'sticker',
sticker: {
mime_type: 'image/webp',
sha256: 'abcd=',
id: '1234',
},
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'location',
location: { latitude: 40.7128, longitude: -74.006, name: 'New York' },
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'contacts',
contacts: [{
name: {
formatted_name: 'John Doe',
first_name: 'John',
},
phones: [{
type: 'HOME',
phone: '0712345678',
}],
emails: [{
type: 'HOME',
email: 'random@random.com',
}],
}],
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'interactive',
interactive: {
type: 'list_reply',
list_reply: {
id: 'random_id_1',
title: 'Item 1',
description: 'Random description',
},
},
context: {
from: '12345678',
id: 'wamid.abcd',
},
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'interactive',
interactive: {
type: 'button_reply',
button_reply: {
id: 'random_id_1',
title: 'Button 1',
},
},
context: {
from: '12345678',
id: 'wamid.abcd',
},
},
{
from: '12345678',
id: 'wamid.abcd',
timestamp: '1640995200',
type: 'interactive',
interactive: {
type: 'nfm_reply',
nfm_reply: {
name: "flow",
body: "Sent",
response_json: {
flow_token: "flows-builder-a0697cdc",
data: {
airtime: {
amount: "10",
currency: "USD",
mobile: "0774166961",
account: "20001901234",
pin: "0000",
fee: "147"
}, msisdn: "263774166961"
},
screen: "ConfirmAirtime"
}
},
},
context: {
from: '12345678',
id: 'wamid.abcd',
},
},
];
let i = 0;
bot.on('message', async (message) => {
expect(message && typeof message === 'object').toBe(true);
expect(message).toHaveProperty('from');
expect(message).toHaveProperty('id');
expect(message).toHaveProperty('timestamp');
expect(message).toHaveProperty('type');
expect(message).toHaveProperty('data');
expect(typeof message.from).toBe('string');
expect(typeof message.id).toBe('string');
expect(typeof message.timestamp).toBe('string');
expect(typeof message.type).toBe('string');
expect(Object.values(pubSub_1.PubSubEvents)).toContain(message.type);
if (message.name) {
expect(typeof message.name).toBe('string');
}
else {
expect(message.name === undefined).toBe(true);
}
expect(typeof message.data === 'object').toBe(true);
const { data } = message;
switch (message.type) {
case 'text':
expect(data).toHaveProperty('text');
expect(typeof data.text).toBe('string');
break;
case 'image':
case 'document':
case 'audio':
case 'video':
case 'sticker':
expect(data).toHaveProperty('mime_type');
expect(data).toHaveProperty('sha256');
expect(data).toHaveProperty('id');
expect(typeof data.mime_type).toBe('string');
expect(typeof data.sha256).toBe('string');
expect(typeof data.id).toBe('string');
if (data.caption) {
expect(typeof data.caption).toBe('string');
}
if (data.filename) {
expect(typeof data.filename).toBe('string');
}
if (data.voice) {
expect(typeof data.voice).toBe('boolean');
}
break;
case 'location':
expect(data).toHaveProperty('latitude');
expect(data).toHaveProperty('longitude');
expect(typeof data.latitude).toBe('number');
expect(typeof data.longitude).toBe('number');
if (data.name) {
expect(typeof data.name).toBe('string');
}
if (data.address) {
expect(typeof data.address).toBe('string');
}
break;
case 'contacts':
expect(Array.isArray(data)).toBe(true);
data.forEach((item) => expect(typeof item === 'object').toBe(true));
break;
case 'list_reply':
case 'button_reply':
expect(data).toHaveProperty('id');
expect(data).toHaveProperty('title');
expect(data).toHaveProperty('context');
expect(typeof data.id).toBe('string');
expect(typeof data.title).toBe('string');
if (data.description) {
expect(typeof data.description).toBe('string');
}
expect(typeof data.context === 'object').toBe(true);
expect(data.context).toHaveProperty('from');
expect(data.context).toHaveProperty('id');
expect(typeof data.context.from).toBe('string');
expect(typeof data.context.id).toBe('string');
break;
case "nfm_reply":
expect(data).toHaveProperty('name');
expect(data).toHaveProperty('body');
expect(data).toHaveProperty('response_json');
expect(typeof data.name).toBe('string');
expect(typeof data.body).toBe('string');
expect(typeof data.response_json === 'object').toBe(true);
expect(data.response_json).toHaveProperty('flow_token');
expect(data.response_json).toHaveProperty('data');
expect(data.response_json).toHaveProperty('screen');
expect(typeof data.response_json.flow_token).toBe('string');
expect(typeof data.response_json.data).toBe('object');
expect(typeof data.response_json.screen).toBe('string');
break;
default:
break;
}
i += 1;
if (i === payloads.length) {
resolve();
}
});
try {
Object.values(payloads).map(async (payload) => {
await (0, supertest_1.default)(app)
.post(webhookPath)
.send({
object: 'abcd',
entry: [{
changes: [{
value: {
messages: [payload],
contacts: [{
profile: {
name: getRandomInt(0, 1) ? 'John Doe' : undefined,
},
}],
metadata: {
phone_number_id: fromPhoneNumberId,
},
},
}],
}],
})
.expect(200);
});
}
catch (err) {
reject(err);
}
}));
});
//# sourceMappingURL=createBot.test.js.map