mg-api-node
Advanced tools
Comparing version 1.0.1 to 1.2.0
59
api.js
var https = require('https'); | ||
var http = require('http'); | ||
var zlib = require('zlib'); | ||
module.exports = function (u, p, d, s, o) { | ||
module.exports = function (u, p, d, s, o, sId) { | ||
var credentials, | ||
@@ -14,9 +14,22 @@ userName = u, | ||
ssl: !o || o.ssl === undefined ? true : o.ssl, | ||
compression: o && o.hasOwnProperty('compression')? o.compression : 'gzip' | ||
}; | ||
compression: o && o.hasOwnProperty('compression') ? o.compression : 'gzip' | ||
}, | ||
sessionId = sId; | ||
if(!userName){ | ||
throw new Error('Must supply userName') | ||
if (!userName) { | ||
throw new Error('Must supply userName') | ||
} | ||
if(!password){ | ||
if (!!sessionId) { | ||
if (!database || directServer === 'my.geotab.com') { | ||
throw new Error('Must supply database and server') | ||
} | ||
credentials = { | ||
userName, | ||
sessionId, | ||
database, | ||
serverName: directServer | ||
} | ||
} else if (!password) { | ||
throw new Error('Must supply password') | ||
@@ -32,3 +45,3 @@ } | ||
} else { | ||
if(!data){ | ||
if (!data) { | ||
callback("no data returned"); | ||
@@ -49,3 +62,3 @@ return; | ||
var encoding = res.headers['content-encoding']; | ||
if(res.statusCode !== 200) { | ||
if (res.statusCode !== 200) { | ||
done({ | ||
@@ -110,4 +123,3 @@ name: res.statusCode.toString(), | ||
}); | ||
} | ||
catch (e) { | ||
} catch (e) { | ||
callback(e, null); | ||
@@ -122,3 +134,3 @@ return; | ||
authenticate(function (err, data) { | ||
if(err){ | ||
if (err) { | ||
callback(err, data); | ||
@@ -131,16 +143,17 @@ } else { | ||
if(!method){ | ||
if (!method) { | ||
throw new Error('Must provide method'); | ||
} | ||
if(!params){ | ||
if (!params) { | ||
params = {}; | ||
} | ||
if(!callback){ | ||
if (!callback) { | ||
throw new Error('Must provide callback'); | ||
} | ||
if(!credentials){ | ||
if (!credentials) { | ||
doAuthenticate(callback); | ||
return; | ||
} | ||
params.credentials = credentials; | ||
@@ -172,6 +185,6 @@ post(method, params, function (err, data) { | ||
if(!calls){ | ||
if (!calls) { | ||
throw new Error('Must provide calls'); | ||
} | ||
if(!callback){ | ||
if (!callback) { | ||
throw new Error('Must provide callback'); | ||
@@ -185,3 +198,3 @@ } | ||
}; | ||
if(!json.params){ | ||
if (!json.params) { | ||
json.params = {}; | ||
@@ -192,3 +205,5 @@ } | ||
call("ExecuteMultiCall", { calls: formattedCalls }, callback); | ||
call("ExecuteMultiCall", { | ||
calls: formattedCalls | ||
}, callback); | ||
}; | ||
@@ -204,3 +219,3 @@ | ||
if(!callback){ | ||
if (!callback) { | ||
throw new Error('Must provide callback'); | ||
@@ -210,3 +225,3 @@ } | ||
post('Authenticate', params, function (err, data) { | ||
if(!err) { | ||
if (!err) { | ||
if (data.path && data.path !== 'ThisServer') { | ||
@@ -228,2 +243,2 @@ directServer = data.path; | ||
} | ||
}; | ||
}; |
{ | ||
"name": "mg-api-node", | ||
"version": "1.0.1", | ||
"version": "1.2.0", | ||
"description": "Unofficial nodejs client for the MyGeotab API", | ||
@@ -5,0 +5,0 @@ "main": "api.js", |
@@ -41,2 +41,25 @@ # mg-api-node # | ||
#### Session ID #### | ||
It's also possible to supply session ID and direct server to re-use a session ID. This avoids costly authentication. | ||
``` | ||
var api = new API(userName, password, database, server, options, sessionId); | ||
api.call('Get', { | ||
typeName: 'User', | ||
resultsLimit: 1 | ||
}, function(err, data) { | ||
if(err){ | ||
console.log('Error', err); | ||
return; | ||
} | ||
console.log('User', data); | ||
}); | ||
``` | ||
### Running Tests ### | ||
@@ -43,0 +66,0 @@ ``` |
472
test/test.js
@@ -9,2 +9,3 @@ var expect = require('chai').expect; | ||
var server = 'my3.geotab.com'; | ||
var sessionId = 'abc1234'; | ||
@@ -15,292 +16,333 @@ var api = new API(userName, password, database); | ||
var credentialsResult = { | ||
result: { | ||
path: server, | ||
credentials: { | ||
userName: userName, | ||
database: database, | ||
sessionId: 'abc1234' | ||
result: { | ||
path: server, | ||
credentials: { | ||
userName: userName, | ||
database: database, | ||
sessionId: sessionId | ||
} | ||
} | ||
} | ||
}; | ||
var invalidUserError = { | ||
error: { | ||
message: 'Incorrect MyGeotab login credentials @ \'g560\'', | ||
name: 'JSONRPCError', | ||
errors: [{ | ||
message: 'Incorrect MyGeotab login credentials @ \'g560\'', | ||
name: 'InvalidUserException' | ||
}] | ||
} | ||
error: { | ||
message: 'Incorrect MyGeotab login credentials @ \'g560\'', | ||
name: 'JSONRPCError', | ||
errors: [{ | ||
message: 'Incorrect MyGeotab login credentials @ \'g560\'', | ||
name: 'InvalidUserException' | ||
}] | ||
} | ||
}; | ||
describe('#authenticate', function() { | ||
var validateSuccess = function(err, data, server) { | ||
expect(err).to.be.a('null'); | ||
describe('#authenticate', function () { | ||
var validateSuccess = function (err, data, server) { | ||
expect(err).to.be.a('null'); | ||
expect(data.path).to.be.a('string'); | ||
expect(data.path).to.equal(server); | ||
expect(data.path).to.be.a('string'); | ||
expect(data.path).to.equal(server); | ||
expect(data.credentials).to.be.a('object'); | ||
expect(data.credentials).to.have.property('userName'); | ||
expect(data.credentials.userName).to.be.a('string').and.to.equal(userName); | ||
expect(data.credentials).to.have.property('sessionId'); | ||
expect(data.credentials.sessionId).to.be.a('string'); | ||
expect(data.credentials).to.have.property('database'); | ||
expect(data.credentials.database).to.be.a('string').and.to.equal(database); | ||
}; | ||
expect(data.credentials).to.be.a('object'); | ||
expect(data.credentials).to.have.property('userName'); | ||
expect(data.credentials.userName).to.be.a('string').and.to.equal(userName); | ||
expect(data.credentials).to.have.property('sessionId'); | ||
expect(data.credentials.sessionId).to.be.a('string'); | ||
expect(data.credentials).to.have.property('database'); | ||
expect(data.credentials.database).to.be.a('string').and.to.equal(database); | ||
}; | ||
it('creates API without userName', function() { | ||
expect(API).to.throw('Must supply userName'); | ||
}); | ||
it('creates API without userName', function () { | ||
expect(API).to.throw('Must supply userName'); | ||
}); | ||
it('creates API without password', function() { | ||
expect(API.bind(API, userName)).to.throw('Must supply password'); | ||
}); | ||
it('creates API without password', function () { | ||
expect(API.bind(API, userName)).to.throw('Must supply password'); | ||
}); | ||
it('authenticate without callback', function() { | ||
api = new API(userName, password, database, server); | ||
expect(api.authenticate).to.throw('Must provide callback'); | ||
}); | ||
it('creates API without session id or password', function () { | ||
expect(API.bind(API, userName)).to.throw('Must supply password'); | ||
}); | ||
it('authenticate against unknown server', function(done) { | ||
api = new API(userName, password, database, 'my10000.geotab.com'); | ||
api.authenticate(function(err, data) { | ||
expect(err).to.be.a('object'); | ||
it('creates API with session id but no database or server', function () { | ||
expect(API.bind(API, userName, null, null, null, null, sessionId)).to.throw('Must supply database and server'); | ||
}); | ||
expect(err.code).to.be.a('string').and.to.equal('ENOTFOUND'); | ||
done(); | ||
it('creates API with session id and a database but no server', function () { | ||
expect(API.bind(API, userName, null, database, null, null, sessionId)).to.throw('Must supply database and server'); | ||
}); | ||
}); | ||
it('handles non 200 response', function(done) { | ||
nock('https://www.example.com').post('/apiv1').reply(404); | ||
it('creates API with session id and a server but no database', function () { | ||
expect(API.bind(API, userName, null, null, server, null, sessionId)).to.throw('Must supply database and server'); | ||
}); | ||
api = new API(userName, password, database, 'www.example.com'); | ||
it('creates API with session id and a database, but a server that equals "my.geotab.com"', function () { | ||
expect(API.bind(API, userName, null, database, "my.geotab.com", null, sessionId)).to.throw('Must supply database and server'); | ||
}); | ||
api.authenticate(function(err, data) { | ||
expect(err).to.be.a('object'); | ||
it('creates API with session id, server, and database', function () { | ||
api = new API(userName, null, database, server, null, sessionId); | ||
expect(api.credentials.userName).to.be.a('string'); | ||
}); | ||
expect(err.message).to.be.a('string'); | ||
expect(err.message).to.equal('Not Found'); | ||
expect(err.name).to.be.a('string'); | ||
expect(err.name).to.equal('404'); | ||
it('authenticate without callback', function () { | ||
api = new API(userName, password, database, server); | ||
expect(api.authenticate).to.throw('Must provide callback'); | ||
}); | ||
done(); | ||
it('authenticate against unknown server', function (done) { | ||
api = new API(userName, password, database, 'my10000.geotab.com'); | ||
api.authenticate(function (err, data) { | ||
expect(err).to.be.a('object'); | ||
expect(err.code).to.be.a('string').and.to.equal('ENOTFOUND'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('authenticates a user successfully [userName, password]', function(done) { | ||
nock('https://my.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
it('handles non 200 response', function (done) { | ||
nock('https://www.example.com').post('/apiv1').reply(404); | ||
api = new API(userName, password); | ||
api = new API(userName, password, database, 'www.example.com'); | ||
api.authenticate(function(err, data) { | ||
validateSuccess(err, data, server); | ||
done(); | ||
api.authenticate(function (err, data) { | ||
expect(err).to.be.a('object'); | ||
expect(err.message).to.be.a('string'); | ||
expect(err.message).to.equal('Not Found'); | ||
expect(err.name).to.be.a('string'); | ||
expect(err.name).to.equal('404'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('authenticates a user successfully [userName, password, database]', function(done) { | ||
nock('https://my.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
it('authenticates a user successfully [userName, password]', function (done) { | ||
nock('https://my.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
api = new API(userName, password, database); | ||
api = new API(userName, password); | ||
api.authenticate(function(err, data) { | ||
validateSuccess(err, data, server); | ||
done(); | ||
api.authenticate(function (err, data) { | ||
validateSuccess(err, data, server); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('authenticates a user successfully [userName, password, database, server]', function(done) { | ||
credentialsResult.result.path = 'ThisServer'; | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
it('authenticates a user successfully [userName, password, database]', function (done) { | ||
nock('https://my.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
api = new API(userName, password, database, server); | ||
api = new API(userName, password, database); | ||
api.authenticate(function(err, data) { | ||
validateSuccess(err, data, 'ThisServer'); | ||
credentialsResult.result.path = 'my3.geotab.com'; | ||
done(); | ||
api.authenticate(function (err, data) { | ||
validateSuccess(err, data, server); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('authenticates with invalid credentials', function(done) { | ||
it('authenticates a user successfully [userName, password, database, server]', function (done) { | ||
credentialsResult.result.path = 'ThisServer'; | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
nock('https://my.geotab.com').post('/apiv1').reply(200, invalidUserError); | ||
api = new API(userName, password, database, server); | ||
api = new API('foo@bar.com', password, database); | ||
api.authenticate(function (err, data) { | ||
validateSuccess(err, data, 'ThisServer'); | ||
credentialsResult.result.path = 'my3.geotab.com'; | ||
done(); | ||
}); | ||
}); | ||
api.authenticate(function(err, data) { | ||
expect(err).to.be.a('object'); | ||
expect(err).to.deep.equal(invalidUserError.error); | ||
done(); | ||
it('authenticates with invalid credentials', function (done) { | ||
nock('https://my.geotab.com').post('/apiv1').reply(200, invalidUserError); | ||
api = new API('foo@bar.com', password, database); | ||
api.authenticate(function (err, data) { | ||
expect(err).to.be.a('object'); | ||
expect(err).to.deep.equal(invalidUserError.error); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#call', function() { | ||
var user = { | ||
result: [{ | ||
name: userName | ||
}] | ||
}; | ||
var version = { | ||
result: "5.7.1234.6" | ||
}; | ||
describe('#call', function () { | ||
var user = { | ||
result: [{ | ||
name: userName | ||
}] | ||
}; | ||
var version = { | ||
result: "5.7.1234.6" | ||
}; | ||
it('gets user', function(done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
it('gets user', function (done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
api = new API(userName, password, database, server); | ||
api = new API(userName, password, database, server); | ||
api.authenticate(function(err, data) { | ||
interceptor = nock('https://my3.geotab.com').post('/apiv1').reply(200, user); | ||
api.call('Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}, function(err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(user.result); | ||
done(); | ||
}); | ||
api.authenticate(function (err, data) { | ||
interceptor = nock('https://my3.geotab.com').post('/apiv1').reply(200, user); | ||
api.call('Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}, function (err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(user.result); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('makes call with no method', function() { | ||
expect(api.call).to.throw('Must provide method'); | ||
}); | ||
it('makes call with no method', function () { | ||
expect(api.call).to.throw('Must provide method'); | ||
}); | ||
it('makes a call without params', function(done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, version); | ||
it('makes a call without params', function (done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, version); | ||
api.call('GetVersion', null, function(err, data) { | ||
expect(err).to.be.a('null'); | ||
api.call('GetVersion', null, function (err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.be.a('string'); | ||
expect(data).to.equal(version.result); | ||
expect(data).to.be.a('string'); | ||
expect(data).to.equal(version.result); | ||
done(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('makes call with callback', function() { | ||
expect(api.call.bind(api.call, 'GetVersion', null)).to.throw('Must provide callback'); | ||
}); | ||
it('makes call with callback', function () { | ||
expect(api.call.bind(api.call, 'GetVersion', null)).to.throw('Must provide callback'); | ||
}); | ||
it('makes a call with unknown method', function(done) { | ||
var error = { | ||
error: { | ||
message: '', | ||
name: 'JSONRPCError', | ||
errors: [{ | ||
message: '', | ||
name: 'MissingMethodException' | ||
}] | ||
} | ||
}; | ||
it('makes a call with unknown method', function (done) { | ||
var error = { | ||
error: { | ||
message: '', | ||
name: 'JSONRPCError', | ||
errors: [{ | ||
message: '', | ||
name: 'MissingMethodException' | ||
}] | ||
} | ||
}; | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
api = new API(userName, password, database, server); | ||
api = new API(userName, password, database, server); | ||
api.authenticate(function(err, data) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, error); | ||
api.authenticate(function (err, data) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, error); | ||
api.call('Get', { | ||
typeName: 'FooBar' | ||
}, function(err, data) { | ||
expect(err).to.be.a('object'); | ||
expect(err).to.deep.equal(error.error); | ||
api.call('Get', { | ||
typeName: 'FooBar' | ||
}, function (err, data) { | ||
expect(err).to.be.a('object'); | ||
expect(err).to.deep.equal(error.error); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('makes a call with no compression', function(done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
it('makes a call with no compression', function (done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
api = new API(userName, password, database, server, { | ||
compression: null | ||
}); | ||
api = new API(userName, password, database, server, { | ||
compression: null | ||
}); | ||
api.authenticate(function(err, data) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, user); | ||
api.authenticate(function (err, data) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, user); | ||
api.call('Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}, function(err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(user.result); | ||
done(); | ||
}); | ||
api.call('Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}, function (err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(user.result); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('re-authenticates and retries on invaliduserexception', function(done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
it('re-authenticates and retries on invaliduserexception', function (done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
api = new API(userName, password, database, server, { | ||
compression: null | ||
api = new API(userName, password, database, server, { | ||
compression: null | ||
}); | ||
api.authenticate(function (err, data) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, invalidUserError) | ||
.post('/apiv1').reply(200, credentialsResult) | ||
.post('/apiv1').reply(200, user); | ||
api.call('Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}, function (err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(user.result); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
api.authenticate(function(err, data) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, invalidUserError) | ||
.post('/apiv1').reply(200, credentialsResult) | ||
.post('/apiv1').reply(200, user); | ||
it('gets user using session id, database, and servername', function (done) { | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, credentialsResult); | ||
api = new API(userName, null, database, server, null, sessionId); | ||
api.call('Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}, function(err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(user.result); | ||
done(); | ||
}); | ||
api.call('Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}, function (err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data.userName).to.equal(user.result.name); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('#multicall', function() { | ||
var calls = [ | ||
['Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}], | ||
['GetVersion'] | ||
]; | ||
describe('#multicall', function () { | ||
var calls = [ | ||
['Get', { | ||
typeName: 'User', | ||
search: { | ||
name: userName | ||
} | ||
}], | ||
['GetVersion'] | ||
]; | ||
it('multicall without calls', function() { | ||
expect(api.multicall).to.throw('Must provide calls'); | ||
}); | ||
it('multicall without calls', function () { | ||
expect(api.multicall).to.throw('Must provide calls'); | ||
}); | ||
it('multicall without callback', function() { | ||
expect(api.multicall.bind(api.multicall, calls, null)).to.throw('Must provide callback'); | ||
}); | ||
it('multicall without callback', function () { | ||
expect(api.multicall.bind(api.multicall, calls, null)).to.throw('Must provide callback'); | ||
}); | ||
it('gets user and version', function(done) { | ||
var results = { | ||
result: [{ | ||
name: userName | ||
}, '5.7.22334.11'] | ||
}; | ||
it('gets user and version', function (done) { | ||
var results = { | ||
result: [{ | ||
name: userName | ||
}, '5.7.22334.11'] | ||
}; | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, results); | ||
nock('https://my3.geotab.com').post('/apiv1').reply(200, results); | ||
api.multicall(calls, function(err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(results.result); | ||
done(); | ||
api.multicall(calls, function (err, data) { | ||
expect(err).to.be.a('null'); | ||
expect(data).to.deep.equal(results.result); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
32609
508
70