ussd-builder
Advanced tools
Comparing version 1.1.3 to 1.1.4
@@ -346,3 +346,4 @@ 'use strict'; | ||
// args.Type = args.MSGTYPE === true ? "Initiation" : "Response"; | ||
args.text = args.USERDATA.length > 0? args.USERDATA : '*920#', | ||
args.text = args.USERDATA.length > 0? args.USERDATA : '', | ||
args.serviceCode = "*920#" | ||
this.args = { | ||
@@ -349,0 +350,0 @@ sessionId: args.MSISDN, |
{ | ||
"name": "ussd-builder", | ||
"version": "1.1.3", | ||
"version": "1.1.4", | ||
"description": "Easily compose USSD menus using states, compatible with Africastalking, Hubtel, Emergent & Nalo Ussd API", | ||
@@ -24,3 +24,5 @@ "main": "index.js", | ||
"emergent ussd", | ||
"interpay" | ||
"interpay", | ||
"nalo", | ||
"arkesel" | ||
], | ||
@@ -27,0 +29,0 @@ "author": "Harmony Alabi <harmonizerblinks@gmail.com>", |
@@ -385,3 +385,2 @@ 'use strict'; | ||
describe('Response', function () { | ||
@@ -688,2 +687,3 @@ let args = { | ||
describe('Error handling', function () { | ||
@@ -1239,2 +1239,3 @@ | ||
describe('Hubtel Support', function () { | ||
@@ -1573,2 +1574,338 @@ let menu; | ||
}); | ||
describe('Emergent Support', function () { | ||
let menu; | ||
let session = {}; | ||
let args; | ||
let config = { | ||
start: (id) => { | ||
return new Promise((resolve, reject) => { | ||
if (!(id in session)) session[id] = {}; | ||
return resolve(); | ||
}); | ||
}, | ||
end: (id) => { | ||
return new Promise((resolve, reject) => { | ||
delete session[id]; | ||
return resolve(); | ||
}); | ||
}, | ||
get: (id, key) => { | ||
return new Promise((resolve, reject) => { | ||
let val = session[id][key]; | ||
return resolve(val); | ||
}); | ||
}, | ||
set: (id, key, val) => { | ||
return new Promise((resolve, reject) => { | ||
session[id][key] = val; | ||
return resolve(); | ||
}); | ||
} | ||
}; | ||
beforeEach(function () { | ||
menu = new UssdMenu({ provider: 'emergent' }); | ||
session = {}; | ||
args = { | ||
Mobile: '233208183783', | ||
SessionId: 'bd7bc392496b4b28af2033ba83f5e400', | ||
ServiceCode: '713*4', | ||
Type: 'Response', | ||
Message: '', | ||
Operator: 'MTN', | ||
Sequence: 2 | ||
}; | ||
}); | ||
it('should emit error when invalid provider in menu config', function (done) { | ||
try { | ||
menu = new UssdMenu({ provider: 'otherTelco' }); | ||
} catch (err) { | ||
expect(err).to.be.an('error'); | ||
done(); | ||
} | ||
}); | ||
it('should emit error when session config not set up', function (done) { | ||
menu = new UssdMenu({ provider: 'emergent' }); | ||
menu.startState({ | ||
run: () => { | ||
menu.con('Next'); | ||
} | ||
}); | ||
menu.on('error', err => { | ||
expect(err).to.be.an('error'); | ||
expect(err.message).to.equal('Session config required for Hubtel provider'); | ||
done(); | ||
}); | ||
menu.run(args); | ||
}); | ||
it('should emit error if unable to map route', function (done) { | ||
menu = new UssdMenu({ provider: 'emergent' }); | ||
args.Message = '1'; | ||
args.Type = 'Initiation'; | ||
let config = { | ||
start: (id, cb) => { | ||
cb(); | ||
}, | ||
get: (id, key) => { | ||
return new Promise((resolve, reject) => { | ||
let val = session[id][key]; | ||
return resolve(val); | ||
}); | ||
}, | ||
set: (id, key, val) => { | ||
return new Promise((resolve, reject) => { | ||
if (key === 'route') { | ||
return reject('Cannot set route key'); | ||
} else { | ||
session[id][key] = val; | ||
return resolve(); | ||
} | ||
}); | ||
}, | ||
end: () => { | ||
return new Promise((resolve, reject) => { | ||
return reject(new Error('end error')); | ||
}); | ||
} | ||
}; | ||
menu.sessionConfig(config); | ||
menu.startState({ | ||
run: () => { | ||
menu.con('Next'); | ||
}, | ||
next: { | ||
'1': 'state1' | ||
} | ||
}); | ||
menu.on('error', err => { | ||
expect(err).to.be.an('error'); | ||
expect(err.message).to.equal('Cannot set route key'); | ||
done(); | ||
}); | ||
menu.run(args); | ||
}); | ||
it('should map incoming emergent request to menu.args', function (done) { | ||
menu.sessionConfig(config); | ||
args.Message = '1'; | ||
menu.startState({ | ||
next: { | ||
'1': 'state1' | ||
} | ||
}); | ||
menu.state('state1', { | ||
run: function (state) { | ||
expect(state.menu.args.phoneNumber).to.equal(`+${args.Mobile}`); | ||
expect(state.menu.args.sessionId).to.equal(args.SessionId); | ||
expect(state.menu.args.serviceCode).to.equal(args.ServiceCode); | ||
expect(state.menu.args.text).to.equal(args.Message); | ||
expect(state.val).to.equal(args.Message); | ||
expect(menu.val).to.equal(args.Message); | ||
done(); | ||
} | ||
}); | ||
menu.run(args); | ||
}); | ||
it('should override message from Initiation call with empty string if no extra params', function(done) { | ||
menu.sessionConfig(config); | ||
const initArgs = Object.assign(args, { | ||
Sequence: 1, | ||
Message: '*789*0#', | ||
Type: 'Initiation', | ||
}); | ||
menu.startState({ | ||
run: function (state) { | ||
expect(menu.val).to.equal(''); | ||
expect(state.menu.args.text).to.equal(''); | ||
done(); | ||
} | ||
}); | ||
menu.run(initArgs); | ||
}); | ||
it('should map Message from Initiation call to a route if extra params', function(done) { | ||
menu.sessionConfig(config); | ||
const initArgs = Object.assign(args, { | ||
Sequence: 1, | ||
Message: '*713*4*3*5#', | ||
Type: 'Initiation', | ||
}); | ||
menu.startState({ | ||
run: function(state){ | ||
// Should not reach this function | ||
expect(10).to.equal(20); | ||
}, | ||
next: { | ||
'3': 'state1' | ||
} | ||
}); | ||
menu.state('state1', { | ||
run: function(state){ | ||
// Should not reach this function | ||
expect(15).to.equal(5); | ||
}, | ||
next: { | ||
'5': 'state2' | ||
} | ||
}); | ||
menu.state('state2', { | ||
run: function(state){ | ||
expect(state.menu.args.phoneNumber).to.equal(`+${args.Mobile}`); | ||
expect(state.menu.args.sessionId).to.equal(args.SessionId); | ||
expect(state.menu.args.serviceCode).to.equal(args.ServiceCode); | ||
expect(state.menu.args.text).to.equal('3*5'); | ||
done(); | ||
}, | ||
next: { | ||
// Should not reach here | ||
'*\\d+': 'state1' | ||
} | ||
}); | ||
menu.run(initArgs); | ||
}); | ||
it('should return Response object from menu.con', function(done) { | ||
menu.sessionConfig(config); | ||
menu.startState({ | ||
run: () => { | ||
menu.con('Next'); | ||
}, | ||
}); | ||
menu.run(args, res => { | ||
expect(res).to.be.an('object'); | ||
expect(res.Message).to.equal('Next'); | ||
expect(res.Type).to.equal('Response'); | ||
done(); | ||
}); | ||
}); | ||
it('should return Release object from menu.end', function (done) { | ||
menu.sessionConfig(config); | ||
menu.startState({ | ||
run: () => { | ||
menu.end('End'); | ||
}, | ||
}); | ||
menu.run(args, res => { | ||
expect(res).to.be.an('object'); | ||
expect(res.Message).to.equal('End'); | ||
expect(res.Type).to.equal('Release'); | ||
done(); | ||
}); | ||
}); | ||
it('should be able to map first text to route', function (done) { | ||
menu.sessionConfig(config); | ||
const testResponse = 'state1 response'; | ||
menu.startState({ | ||
run: () => { | ||
menu.con('Next'); | ||
}, | ||
next: { | ||
'1': 'state1' | ||
} | ||
}); | ||
menu.state('state1', { | ||
run: () => { | ||
menu.con(testResponse); | ||
} | ||
}); | ||
menu.run(args, () => { | ||
expect(session[args.SessionId].route).to.equal(''); | ||
args.Message = '1'; | ||
menu.run(args, res => { | ||
process.nextTick(() => { | ||
// expect session to be deleted | ||
expect(res.Message).to.equal(testResponse); | ||
expect(session[args.SessionId].route).to.equal(args.Message); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should be able to map text after first sequence to route', function (done) { | ||
menu.sessionConfig(config); | ||
const initArgs = Object.assign({}, args, { | ||
Sequence: 1, | ||
Message: '*713*4#', | ||
Type: 'Initiation', | ||
}); | ||
const firstResponseArgs = Object.assign({}, args, { | ||
Sequence: 2, | ||
Message: '1', | ||
}); | ||
const secondResponseArgs = Object.assign({}, args, { | ||
Sequence: 3, | ||
Message: '3', | ||
}); | ||
const testResponse = 'state1 response'; | ||
const test2Response = 'state2 response'; | ||
menu.startState({ | ||
run: () => { | ||
menu.con('Next'); | ||
}, | ||
next: { | ||
'1': 'state1' | ||
} | ||
}); | ||
menu.state('state1', { | ||
run: () => { | ||
menu.con(testResponse); | ||
}, | ||
next: { | ||
'3': 'state2' | ||
} | ||
}); | ||
menu.state('state2', { | ||
run: () => { | ||
menu.end(test2Response); | ||
} | ||
}); | ||
menu.run(initArgs, initResponse => { | ||
expect(session[args.SessionId].route).to.equal(''); | ||
expect(initResponse.Message).to.equal('Next'); | ||
expect(initResponse.Type).to.equal('Response'); | ||
menu.run(firstResponseArgs, res => { | ||
// expect session to be deleted | ||
expect(res.Message).to.equal(testResponse); | ||
expect(res.Type).to.equal('Response'); | ||
menu.run(secondResponseArgs, res2 => { | ||
expect(res2.Message).to.equal(test2Response); | ||
expect(res2.Type).to.equal('Release'); | ||
expect(session[args.SessionId].route).to.equal('1*3'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe("Menu Run Returns Promise", function () { | ||
@@ -1575,0 +1912,0 @@ it('menu.run should return a resolvable promise', function (done) { |
105140
2228