mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-19 04:17:44 +00:00
ws-requestor unit test (#244)
* ws-requestor unit test * ws-requestor unit test * ws-requestor unit test * handle special case of reconnecting during the initial session:new - ack transaction * fix: add more wsrequestor unit test * fix: add more wsrequestor unit test --------- Co-authored-by: Quan HL <quanluuhoang8@gmail.com> Co-authored-by: Dave Horton <daveh@beachdognet.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
require('./ws-requestor-unit-test')
|
||||
require('./unit-tests');
|
||||
require('./docker_start');
|
||||
require('./create-test-db');
|
||||
|
||||
97
test/ws-mock.js
Normal file
97
test/ws-mock.js
Normal file
@@ -0,0 +1,97 @@
|
||||
class MockWebsocket {
|
||||
static eventResponses = new Map();
|
||||
static actionLoops = new Map();
|
||||
eventListeners = new Map();
|
||||
|
||||
constructor(url, protocols, options) {
|
||||
this.u = url;
|
||||
this.pros = protocols;
|
||||
this.opts = options;
|
||||
setTimeout(() => {
|
||||
this.open();
|
||||
}, 500)
|
||||
}
|
||||
|
||||
static addJsonMapping(key, value) {
|
||||
MockWebsocket.eventResponses.set(key, value);
|
||||
}
|
||||
|
||||
static getAndIncreaseActionLoops(key) {
|
||||
const ret = MockWebsocket.actionLoops.has(key) ? MockWebsocket.actionLoops.get(key) : 0;
|
||||
MockWebsocket.actionLoops.set(key, ret + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
once(event, listener) {
|
||||
// Websocket.ws = this;
|
||||
this.eventListeners.set(event, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
on(event, listener) {
|
||||
// Websocket.ws = this;
|
||||
this.eventListeners.set(event, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
open() {
|
||||
if (this.eventListeners.has('open')) {
|
||||
this.eventListeners.get('open')();
|
||||
}
|
||||
}
|
||||
|
||||
removeAllListeners() {
|
||||
this.eventListeners.clear();
|
||||
}
|
||||
|
||||
send(data, callback) {
|
||||
const json = JSON.parse(data);
|
||||
console.log({json}, 'got message from ws-requestor');
|
||||
if (MockWebsocket.eventResponses.has(json.call_sid)) {
|
||||
|
||||
const resp_data = MockWebsocket.eventResponses.get(json.call_sid);
|
||||
const action = resp_data.action[MockWebsocket.getAndIncreaseActionLoops(json.call_sid)];
|
||||
if (action === 'connect') {
|
||||
setTimeout(()=> {
|
||||
const msg = {
|
||||
type: 'ack',
|
||||
msgid: json.msgid,
|
||||
command: 'command',
|
||||
call_sid: json.call_sid,
|
||||
queueCommand: false,
|
||||
data: resp_data.body}
|
||||
console.log({msg}, 'sending ack to ws-requestor');
|
||||
this.mockOnMessage(JSON.stringify(msg));
|
||||
}, 100);
|
||||
} else if (action === 'close') {
|
||||
if (this.eventListeners.has('close')) {
|
||||
this.eventListeners.get('close')(500);
|
||||
}
|
||||
} else if (action === 'terminate') {
|
||||
if (this.eventListeners.has('close')) {
|
||||
this.eventListeners.get('close')(1000);
|
||||
}
|
||||
} else if (action === 'error') {
|
||||
if (this.eventListeners.has('error')) {
|
||||
this.eventListeners.get('error')();
|
||||
}
|
||||
} else if (action === 'unexpected-response') {
|
||||
if (this.eventListeners.has('unexpected-response')) {
|
||||
this.eventListeners.get('unexpected-response')();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
mockOnMessage(message, isBinary=false) {
|
||||
if (this.eventListeners.has('message')) {
|
||||
this.eventListeners.get('message')(message, isBinary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MockWebsocket;
|
||||
198
test/ws-requestor-unit-test.js
Normal file
198
test/ws-requestor-unit-test.js
Normal file
@@ -0,0 +1,198 @@
|
||||
const test = require('tape');
|
||||
const sinon = require('sinon');
|
||||
const proxyquire = require("proxyquire");
|
||||
proxyquire.noCallThru();
|
||||
const MockWebsocket = require('./ws-mock')
|
||||
const logger = require('pino')({level: process.env.JAMBONES_LOGLEVEL || 'error'});
|
||||
|
||||
const BaseRequestor = proxyquire(
|
||||
"../lib/utils/base-requestor",
|
||||
{
|
||||
"../../": {
|
||||
srf: {
|
||||
locals: {
|
||||
stats: {
|
||||
histogram: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@jambonz/time-series": sinon.stub()
|
||||
}
|
||||
);
|
||||
|
||||
const WsRequestor = proxyquire(
|
||||
"../lib/utils/ws-requestor",
|
||||
{
|
||||
"./base-requestor": BaseRequestor,
|
||||
"ws": MockWebsocket
|
||||
}
|
||||
);
|
||||
|
||||
test('ws success', async (t) => {
|
||||
// GIVEN
|
||||
|
||||
const json = '[{\"verb\": \"play\",\"url\": \"silence_stream://5000\"}]';
|
||||
const ws_response = {
|
||||
action: ['connect'],
|
||||
body: json
|
||||
}
|
||||
const call_sid = 'ws_success';
|
||||
|
||||
MockWebsocket.addJsonMapping(call_sid, ws_response);
|
||||
|
||||
const hook = {
|
||||
url: 'ws://localhost:3000',
|
||||
username: 'username',
|
||||
password: 'password'
|
||||
}
|
||||
|
||||
const params = {
|
||||
callSid: call_sid
|
||||
}
|
||||
|
||||
// WHEN
|
||||
|
||||
const requestor = new WsRequestor(logger, "account_sid", hook, "webhook_secret");
|
||||
const result = await requestor.request('session:new',hook, params, {});
|
||||
|
||||
// THEN
|
||||
t.ok(result == json,'ws successfully sent session:new and got initial jambonz app');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('ws close success reconnect', async (t) => {
|
||||
// GIVEN
|
||||
|
||||
const call_sid = 'ws_closed'
|
||||
const json = '[{\"verb\": \"play\",\"url\": \"silence_stream://5000\"}]';
|
||||
const ws_response = {
|
||||
action: ['close', 'connect'],
|
||||
body: json
|
||||
}
|
||||
MockWebsocket.addJsonMapping(call_sid, ws_response);
|
||||
|
||||
const hook = {
|
||||
url: 'ws://localhost:3000',
|
||||
username: 'username',
|
||||
password: 'password'
|
||||
}
|
||||
|
||||
const params = {
|
||||
callSid: call_sid
|
||||
}
|
||||
|
||||
// WHEN
|
||||
|
||||
const requestor = new WsRequestor(logger, "account_sid", hook, "webhook_secret");
|
||||
const result = await requestor.request('session:new',hook, params, {});
|
||||
|
||||
// THEN
|
||||
t.ok(result == json,'ws successfully reconnect after close from far end');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('ws response error 1000', async (t) => {
|
||||
// GIVEN
|
||||
|
||||
const call_sid = 'ws_terminated'
|
||||
const json = '[{\"verb\": \"play\",\"url\": \"silence_stream://5000\"}]';
|
||||
const ws_response = {
|
||||
action: ['terminate'],
|
||||
body: json
|
||||
}
|
||||
MockWebsocket.addJsonMapping(call_sid, ws_response);
|
||||
|
||||
const hook = {
|
||||
url: 'ws://localhost:3000',
|
||||
username: 'username',
|
||||
password: 'password'
|
||||
}
|
||||
|
||||
const params = {
|
||||
callSid: call_sid
|
||||
}
|
||||
|
||||
// WHEN
|
||||
|
||||
const requestor = new WsRequestor(logger, "account_sid", hook, "webhook_secret");
|
||||
try {
|
||||
await requestor.request('session:new',hook, params, {});
|
||||
}
|
||||
catch (err) {
|
||||
// THEN
|
||||
t.ok(err.startsWith('timeout from far end for msgid'), 'ws does not reconnect if far end closes gracefully');
|
||||
t.end();
|
||||
}
|
||||
});
|
||||
|
||||
test('ws response error', async (t) => {
|
||||
// GIVEN
|
||||
|
||||
const call_sid = 'ws_error'
|
||||
const json = '[{\"verb\": \"play\",\"url\": \"silence_stream://5000\"}]';
|
||||
const ws_response = {
|
||||
action: ['error'],
|
||||
body: json
|
||||
}
|
||||
MockWebsocket.addJsonMapping(call_sid, ws_response);
|
||||
|
||||
const hook = {
|
||||
url: 'ws://localhost:3000',
|
||||
username: 'username',
|
||||
password: 'password'
|
||||
}
|
||||
|
||||
const params = {
|
||||
callSid: call_sid
|
||||
}
|
||||
|
||||
// WHEN
|
||||
|
||||
const requestor = new WsRequestor(logger, "account_sid", hook, "webhook_secret");
|
||||
try {
|
||||
await requestor.request('session:new',hook, params, {});
|
||||
}
|
||||
catch (err) {
|
||||
// THEN
|
||||
t.ok(err.startsWith('timeout from far end for msgid'), 'ws does not reconnect if far end closes gracefully');
|
||||
t.end();
|
||||
}
|
||||
});
|
||||
|
||||
test('ws unexpected-response', async (t) => {
|
||||
// GIVEN
|
||||
|
||||
const call_sid = 'ws_unexpected-response'
|
||||
const json = '[{\"verb\": \"play\",\"url\": \"silence_stream://5000\"}]';
|
||||
const ws_response = {
|
||||
action: ['unexpected-response'],
|
||||
body: json
|
||||
}
|
||||
MockWebsocket.addJsonMapping(call_sid, ws_response);
|
||||
|
||||
const hook = {
|
||||
url: 'ws://localhost:3000',
|
||||
username: 'username',
|
||||
password: 'password'
|
||||
}
|
||||
|
||||
const params = {
|
||||
callSid: call_sid
|
||||
}
|
||||
|
||||
// WHEN
|
||||
|
||||
const requestor = new WsRequestor(logger, "account_sid", hook, "webhook_secret");
|
||||
try {
|
||||
await requestor.request('session:new',hook, params, {});
|
||||
}
|
||||
catch (err) {
|
||||
// THEN
|
||||
t.ok(err.code = 'ERR_ASSERTION', 'ws does not reconnect if far end closes gracefully');
|
||||
t.end();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user