ebay-api
Advanced tools
Comparing version 1.1.0 to 1.2.0
13
index.js
// eBay API client for Node.js | ||
exports.xmlRequest = require('./lib/xml-request').xmlRequest; | ||
var _ = require('lodash'); | ||
exports.paginatedRequest = require('./lib/pagination').paginatedRequest; | ||
var parser = require('./lib/parser'); | ||
exports.parseResponse = parser.parseResponse; | ||
exports.flatten = parser.flatten; | ||
module.exports = _.extend({}, | ||
require('./lib/xml-request'), | ||
require('./lib/pagination'), | ||
require('./lib/parser'), | ||
require('./lib/errors') | ||
); |
var | ||
_ = require('lodash'), | ||
util = require('util'), | ||
debug = require('debug')('ebay:parser'); | ||
debug = require('debug')('ebay:parser'), | ||
_errors = require('./errors'), | ||
EbaySystemError = _errors.EbaySystemError, | ||
EbayRequestError = _errors.EbayRequestError, | ||
EbayClientError = _errors.EbayClientError; | ||
/* | ||
@@ -142,6 +147,7 @@ helper: find an array containing only special key-value pairs | ||
@param options: context on the request. | ||
@return parsed object. | ||
@throws exception on failure, or if error message is parsed from response. | ||
@param callback: gets `null, data` in success case, and `error, data` on error case. | ||
- error can be from response or parsing failure. (see error types.) | ||
- callback is actually called immediately/synchronously - just using to have 2 return values in error case. | ||
*/ | ||
exports.parseResponse = function(data, options) { | ||
exports.parseResponse = function(data, options, callback) { | ||
debug('parsing items', data); | ||
@@ -157,29 +163,68 @@ | ||
if (_.isUndefined(data)) { | ||
throw new Error("Response missing " + responseKey + " element"); | ||
// assume this is a failure of the client to parse the response properly. | ||
throw new EbayClientError("Response missing " + responseKey + " element"); | ||
} | ||
// 'ack' and 'errorMessage' indicate errors. | ||
// in FindingService it's nested (?), in others it's flat - flatten to normalize. | ||
var errorMessage, errors; | ||
if (!_.isUndefined(data.Ack)) { // normalize to lowercase | ||
data.ack = data.Ack; | ||
delete data.Ack; | ||
} | ||
// | ||
// 'Ack', 'Errors', (and maybe 'errorMessage'?) indicate errors. | ||
// see http://developer.ebay.com/devzone/xml/docs/Reference/ebay/Errors/ErrorMessages.htm | ||
// | ||
var | ||
errorMessage, // build a string | ||
errorClassification = 'RequestError', // 'RequestError' or 'SystemError' | ||
errors; // error object(s) in response. | ||
// normalize to uppercase | ||
if (!_.isUndefined(data.ack)) { | ||
data.ack = flatten(data.ack); | ||
data.Ack = data.ack; | ||
delete data.ack; | ||
} | ||
if (_.isUndefined(data.ack) || data.ack !== 'Success') { | ||
if (!_.isUndefined(data.errorMessage)) { | ||
errorMessage = flatten(data.errorMessage); | ||
if (_.isObject(errorMessage)) errorMessage = util.inspect(errorMessage, true, 3); | ||
} | ||
else if (!_.isUndefined(data.Errors)) { | ||
if (!_.isUndefined(data.Ack)) { | ||
data.Ack = flatten(data.Ack); | ||
} | ||
// | ||
// note: docs say, | ||
// "Both Success and Warning indicate that the request was successful. | ||
// However, a value of Warning means that something occurred | ||
// that may affect your application or the user." | ||
// for now, treat Warning as a failure. | ||
// | ||
if (_.isUndefined(data.Ack) || data.Ack !== 'Success') { | ||
// | ||
// handle all different ways errors can be represented | ||
// | ||
// Trading, Shopping, Finding(?) | ||
if (!_.isUndefined(data.Errors)) { | ||
errors = _.isArray(data.Errors) ? data.Errors : [data.Errors]; | ||
// build composite message. | ||
errorMessage = errors.map(function(errorObj) { | ||
errorObj = flatten(errorObj); | ||
return errorObj.LongMessage + '(' + errorObj.ErrorCode + ').'; | ||
}).join(' '); | ||
if (errorObj.ErrorClassification === 'SystemError') { | ||
errorClassification = 'SystemError'; // trumps RequestError | ||
} | ||
return errorObj.LongMessage + (errorObj.ErrorCode ? ' (' + errorObj.ErrorCode + ')' : ''); | ||
}).join(', '); | ||
} | ||
debug('data errors', data.ack, errorMessage); | ||
throw new Error(util.format("Bad ack code: ", data.ack, errorMessage ? ' - ' + errorMessage : '')); | ||
// @review which API is this for? | ||
// (maybe a relic of JSON response, no longer relevant?) | ||
else if (!_.isUndefined(data.errorMessage)) { | ||
errorMessage = flatten(data.errorMessage); | ||
if (_.isObject(errorMessage)) errorMessage = util.inspect(errorMessage, true, 3); | ||
// TODO error code and classification in this format? | ||
} | ||
debug('response error', errorClassification, data.Ack, errorMessage); | ||
if (!errorMessage) errorMessage = util.format("Bad ack code: ", data.Ack); // fallback | ||
if (errorClassification === 'SystemError') { | ||
return callback(new EbaySystemError("eBay API system error: " + errorMessage), data); | ||
} | ||
else { | ||
return callback(new EbayRequestError("eBay API request error: " + errorMessage), data); | ||
} | ||
} | ||
@@ -200,3 +245,3 @@ | ||
return data; | ||
callback(null, data); | ||
}; |
@@ -11,5 +11,11 @@ var | ||
getDefaultHeaders = require('./defaults').getDefaultHeaders, | ||
defaultParser = require('./parser').parseResponse; | ||
defaultParser = require('./parser').parseResponse, | ||
_errors = require('./errors'), | ||
EbaySystemError = _errors.EbaySystemError, | ||
EbayRequestError = _errors.EbayRequestError, | ||
EbayClientError = _errors.EbayClientError; | ||
/** | ||
@@ -142,9 +148,9 @@ * handle quirk of 'xml' module: | ||
//if (response.body instanceof Error) { // @review necessary? | ||
// var error = response.body; | ||
// error.message = "Completed with error: " + error.message; | ||
// return callback(error); | ||
//} | ||
// this is tricky -- API should return 200 with body in every valid scenario, | ||
// so a non-200 probably means something's wrong on the client side with the request. | ||
// so expect an EbayClientError. | ||
if (response.statusCode !== 200) { | ||
return callback(new Error(util.format("Bad response status code", response.statusCode, response.body.toString()))); | ||
return callback(new EbayClientError( | ||
util.format("Bad response status code", response.statusCode, (response.body ? response.body.toString() : null)) | ||
)); | ||
} | ||
@@ -163,5 +169,4 @@ | ||
if (error) { | ||
error.message = "Error parsing XML: " + error.message; | ||
debug(error); | ||
return next(error); | ||
return next(new EbayClientError("Error parsing XML: " + error.message)); | ||
} | ||
@@ -174,15 +179,24 @@ debug('Parsed XML', data); | ||
function _parseJson(data, next) { | ||
var parsed; | ||
try { | ||
parsed = options.parser(data, options); | ||
next(null, parsed); | ||
// will pass error if response includes an error message, | ||
// or if actually can't parse. | ||
options.parser(data, options, next); | ||
} | ||
], | ||
function _done(error, data) { | ||
if (error) { | ||
if (/Ebay/i.test(error.name)) { | ||
callback(error, data); // already differentiated | ||
} | ||
catch(error) { | ||
error.message = "Error parsing JSON: " + error.message; | ||
next(error) | ||
else { | ||
// some other parsing error | ||
// @review - is the original stack trace lost here? | ||
callback(new EbayClientError("Error parsing JSON: " + error.message), data); | ||
} | ||
} | ||
], | ||
callback); | ||
else { | ||
callback(null, data); | ||
} | ||
}); | ||
}); | ||
}; |
{ | ||
"name": "ebay-api", | ||
"description": "eBay API Client", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"homepage": "https://github.com/newleafdigital/nodejs-ebay-api", | ||
@@ -6,0 +6,0 @@ "author": "Ben Buckman <ben@newleafdigital.com> (http://newleafdigital.com)", |
@@ -98,9 +98,2 @@ eBay API client for Node.js | ||
## Debugging | ||
This module uses the [debug](https://github.com/visionmedia/debug) module for internal logging. | ||
Run your app (or node REPL) with `DEBUG=ebay* ...` to see output. | ||
## Helpers | ||
@@ -132,2 +125,10 @@ | ||
## Errors | ||
The client exports and attempts to differentiate between `EbaySystemError`, `EbayRequestError`, and `EbayClientError`. | ||
See http://developer.ebay.com/DevZone/Shopping/docs/CallRef/types/ErrorClassificationCodeType.html | ||
and http://developer.ebay.com/devzone/xml/docs/Reference/ebay/Errors/ErrorMessages.htm. | ||
## Examples | ||
@@ -143,2 +144,9 @@ | ||
## Debugging | ||
This module uses the [debug](https://github.com/visionmedia/debug) module for internal logging. | ||
Run your app (or node REPL) with `DEBUG=ebay* ...` to see output. | ||
Enjoy! | ||
@@ -145,0 +153,0 @@ |
@@ -10,157 +10,166 @@ var | ||
request = require('request'), | ||
xmlRequest = require('../index').xmlRequest; | ||
ebay = require('../index') | ||
xmlRequest = ebay.xmlRequest; | ||
describe('XML requests', function() { | ||
beforeEach(function() { | ||
sinon.stub(request, 'post', function(options, callback) { | ||
process.nextTick(function() { | ||
callback(null, {statusCode: 200}, {}); | ||
}); | ||
}); | ||
beforeEach('sandbox', function() { | ||
this.sinon = sinon.sandbox.create(); | ||
}); | ||
afterEach(function() { | ||
request.post.restore(); | ||
afterEach('unstub', function() { | ||
this.sinon.restore(); | ||
}); | ||
describe('Shopping: GetSingleItem', function() { | ||
beforeEach('build request', function() { | ||
xmlRequest({ | ||
serviceName: 'Shopping', | ||
opType: 'GetSingleItem', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
'ItemID': '123456' | ||
}, | ||
reqOptions: { | ||
describe('building requests', function() { | ||
beforeEach('stub request', function () { | ||
this.sinon.stub(request, 'post', function (options, callback) { | ||
process.nextTick(function () { | ||
callback(null, {statusCode: 200}, {}); | ||
}); | ||
}); | ||
}); | ||
describe('Shopping: GetSingleItem', function () { | ||
beforeEach('build request', function () { | ||
xmlRequest({ | ||
serviceName: 'Shopping', | ||
opType: 'GetSingleItem', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
'ItemID': '123456' | ||
}, | ||
reqOptions: { | ||
headers: { | ||
'X-Extra': 'um' | ||
} | ||
} | ||
}, function noop() { | ||
}); | ||
}); | ||
it('initiated request with expected parameters', function () { | ||
expect(request.post).to.have.been.calledOnce; | ||
expect(request.post.lastCall.args[0]).to.deep.equal({ | ||
url: 'http://open.api.sandbox.ebay.com/shopping', | ||
headers: { | ||
'Content-Type': 'text/xml', | ||
'X-EBAY-API-APP-ID': 'ABCDEF', | ||
'X-EBAY-API-CALL-NAME': 'GetSingleItem', | ||
'X-EBAY-API-VERSION': '897', | ||
'X-EBAY-API-SITE-ID': '0', | ||
'X-EBAY-API-REQUEST-ENCODING': 'XML', | ||
'X-EBAY-API-RESPONSE-ENCODING': 'XML', | ||
'X-Extra': 'um' | ||
} | ||
} | ||
}, function noop(){}); | ||
}, | ||
body: '<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetSingleItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <ItemID>123456</ItemID>\n' + | ||
'</GetSingleItemRequest>' | ||
}); | ||
}) | ||
}); | ||
it('initiated request with expected parameters', function() { | ||
expect(request.post).to.have.been.calledOnce; | ||
expect(request.post.lastCall.args[0]).to.deep.equal({ | ||
url: 'http://open.api.sandbox.ebay.com/shopping', | ||
headers: { | ||
'Content-Type': 'text/xml', | ||
'X-EBAY-API-APP-ID': 'ABCDEF', | ||
'X-EBAY-API-CALL-NAME': 'GetSingleItem', | ||
'X-EBAY-API-VERSION': '897', | ||
'X-EBAY-API-SITE-ID': '0', | ||
'X-EBAY-API-REQUEST-ENCODING': 'XML', | ||
'X-EBAY-API-RESPONSE-ENCODING': 'XML', | ||
'X-Extra': 'um' | ||
}, | ||
body: '<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetSingleItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <ItemID>123456</ItemID>\n' + | ||
'</GetSingleItemRequest>' | ||
describe('Shopping: GetMultipleItems', function () { | ||
beforeEach('build request', function () { | ||
xmlRequest({ | ||
serviceName: 'Shopping', | ||
opType: 'GetMultipleItems', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
'ItemID': ['123456', '345678'] | ||
} | ||
}, function noop() { | ||
}); | ||
}); | ||
}) | ||
}); | ||
describe('Shopping: GetMultipleItems', function() { | ||
beforeEach('build request', function() { | ||
xmlRequest({ | ||
serviceName: 'Shopping', | ||
opType: 'GetMultipleItems', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
'ItemID': ['123456', '345678'] | ||
} | ||
}, function noop(){}); | ||
it('handles multiple parameter values', function () { | ||
expect(request.post).to.have.been.calledOnce; | ||
expect(request.post.lastCall.args[0]).to.have.property('body', | ||
'<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetMultipleItemsRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <ItemID>123456</ItemID>\n' + | ||
' <ItemID>345678</ItemID>\n' + | ||
'</GetMultipleItemsRequest>' | ||
); | ||
}) | ||
}); | ||
it('handles multiple parameter values', function() { | ||
expect(request.post).to.have.been.calledOnce; | ||
expect(request.post.lastCall.args[0]).to.have.property('body', | ||
'<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetMultipleItemsRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <ItemID>123456</ItemID>\n' + | ||
' <ItemID>345678</ItemID>\n' + | ||
'</GetMultipleItemsRequest>' | ||
); | ||
}) | ||
}); | ||
describe('Trading: GetOrders (authenticated)', function () { | ||
beforeEach('build request', function () { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrders', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
authToken: 'super-secret', | ||
raw: true, // no parsing | ||
params: { | ||
'NumberOfDays': '30' | ||
} | ||
}, function noop() { | ||
}); | ||
}); | ||
describe('Trading: GetOrders (authenticated)', function() { | ||
beforeEach('build request', function() { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrders', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
authToken: 'super-secret', | ||
raw: true, // no parsing | ||
params: { | ||
'NumberOfDays': '30' | ||
} | ||
}, function noop(){}); | ||
it('adds token to XML request', function () { | ||
expect(request.post.lastCall.args[0]).to.have.property('body', | ||
'<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetOrdersRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <RequesterCredentials>\n' + | ||
' <eBayAuthToken>super-secret</eBayAuthToken>\n' + | ||
' </RequesterCredentials>\n' + | ||
' <NumberOfDays>30</NumberOfDays>\n' + | ||
'</GetOrdersRequest>' | ||
); | ||
}); | ||
}); | ||
it('adds token to XML request', function() { | ||
expect(request.post.lastCall.args[0]).to.have.property('body', | ||
'<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetOrdersRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <RequesterCredentials>\n' + | ||
' <eBayAuthToken>super-secret</eBayAuthToken>\n' + | ||
' </RequesterCredentials>\n' + | ||
' <NumberOfDays>30</NumberOfDays>\n' + | ||
'</GetOrdersRequest>' | ||
); | ||
}); | ||
}); | ||
describe('Finding: findItemsByKeywords', function() { | ||
beforeEach('build request', function () { | ||
xmlRequest({ | ||
serviceName: 'Finding', | ||
opType: 'findItemsByKeywords', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
keywords: ['Canon', 'Powershot'], | ||
outputSelector: ['AspectHistogram'], | ||
itemFilter: [ | ||
{name: 'FreeShippingOnly', value: 'true'}, | ||
{name: 'MaxPrice', value: '150'}, | ||
], | ||
domainFilter: [ | ||
{name: 'domainName', value: 'Digital_Cameras'} | ||
], | ||
paginationInput: { | ||
entriesPerPage: '5' | ||
describe('Finding: findItemsByKeywords', function () { | ||
beforeEach('build request', function () { | ||
xmlRequest({ | ||
serviceName: 'Finding', | ||
opType: 'findItemsByKeywords', | ||
sandbox: true, | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
keywords: ['Canon', 'Powershot'], | ||
outputSelector: ['AspectHistogram'], | ||
itemFilter: [ | ||
{name: 'FreeShippingOnly', value: 'true'}, | ||
{name: 'MaxPrice', value: '150'}, | ||
], | ||
domainFilter: [ | ||
{name: 'domainName', value: 'Digital_Cameras'} | ||
], | ||
paginationInput: { | ||
entriesPerPage: '5' | ||
} | ||
} | ||
} | ||
}, function noop() { | ||
}, function noop() { | ||
}); | ||
}); | ||
}); | ||
it('initiated request with expected parameters', function() { | ||
expect(request.post).to.have.been.calledOnce; | ||
it('initiated request with expected parameters', function () { | ||
expect(request.post).to.have.been.calledOnce; | ||
expect(request.post.lastCall.args[0]).to.deep.equal({ | ||
url: 'http://svcs.sandbox.ebay.com/services/search/FindingService/v1', | ||
headers: { | ||
'X-EBAY-SOA-SECURITY-APPNAME': 'ABCDEF', | ||
'X-EBAY-SOA-REQUEST-DATA-FORMAT': 'XML', | ||
'X-EBAY-SOA-RESPONSE-DATA-FORMAT': 'XML', | ||
'X-EBAY-SOA-GLOBAL-ID': 'EBAY-US', | ||
'X-EBAY-SOA-SERVICE-VERSION': '1.13.0', | ||
'X-EBAY-SOA-OPERATION-NAME': 'findItemsByKeywords' | ||
}, | ||
body: | ||
'<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
expect(request.post.lastCall.args[0]).to.deep.equal({ | ||
url: 'http://svcs.sandbox.ebay.com/services/search/FindingService/v1', | ||
headers: { | ||
'X-EBAY-SOA-SECURITY-APPNAME': 'ABCDEF', | ||
'X-EBAY-SOA-REQUEST-DATA-FORMAT': 'XML', | ||
'X-EBAY-SOA-RESPONSE-DATA-FORMAT': 'XML', | ||
'X-EBAY-SOA-GLOBAL-ID': 'EBAY-US', | ||
'X-EBAY-SOA-SERVICE-VERSION': '1.13.0', | ||
'X-EBAY-SOA-OPERATION-NAME': 'findItemsByKeywords' | ||
}, | ||
body: '<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<findItemsByKeywordsRequest xmlns="http://www.ebay.com/marketplace/search/v1/services">\n' + | ||
@@ -186,40 +195,196 @@ ' <keywords>Canon</keywords>\n' + | ||
'</findItemsByKeywordsRequest>' | ||
}); | ||
}); | ||
}); | ||
describe('nested params', function () { | ||
beforeEach('build request', function () { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrderTransactions', | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
'ItemTransactionIDArray': [{ | ||
'ItemTransactionID': { | ||
'OrderLineItemID': '12345-67890', | ||
'SomeOtherID': 'ABCDEF' | ||
} | ||
}] | ||
} | ||
}, function noop() { | ||
}); | ||
}); | ||
it('converts properly to nested XML', function () { | ||
expect(request.post.lastCall.args[0]).to.have.property('body', | ||
'<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetOrderTransactionsRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <ItemTransactionIDArray>\n' + | ||
' <ItemTransactionID>\n' + | ||
' <OrderLineItemID>12345-67890</OrderLineItemID>\n' + | ||
' <SomeOtherID>ABCDEF</SomeOtherID>\n' + | ||
' </ItemTransactionID>\n' + | ||
' </ItemTransactionIDArray>\n' + | ||
'</GetOrderTransactionsRequest>' | ||
); | ||
}) | ||
}); | ||
}); | ||
describe('nested params', function() { | ||
beforeEach('build request', function() { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrderTransactions', | ||
appId: 'ABCDEF', | ||
raw: true, // no parsing | ||
params: { | ||
'ItemTransactionIDArray': [{ | ||
'ItemTransactionID': { | ||
'OrderLineItemID': '12345-67890', | ||
'SomeOtherID': 'ABCDEF' | ||
} | ||
}] | ||
} | ||
}, function noop(){}); | ||
describe('response error handling', function() { | ||
var err, data; | ||
beforeEach(function() { | ||
err = null; | ||
data = null; | ||
}); | ||
it('converts properly to nested XML', function() { | ||
expect(request.post.lastCall.args[0]).to.have.property('body', | ||
'<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetOrderTransactionsRequest xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <ItemTransactionIDArray>\n' + | ||
' <ItemTransactionID>\n' + | ||
' <OrderLineItemID>12345-67890</OrderLineItemID>\n' + | ||
' <SomeOtherID>ABCDEF</SomeOtherID>\n' + | ||
' </ItemTransactionID>\n' + | ||
' </ItemTransactionIDArray>\n' + | ||
'</GetOrderTransactionsRequest>' | ||
); | ||
}) | ||
}); | ||
function _buildResponseCallback(errorCode, errorClassification) { | ||
return function(options, callback) { | ||
process.nextTick(function() { | ||
callback(null, { | ||
statusCode: 200, | ||
body: '<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
'<GetOrdersResponse xmlns="urn:ebay:apis:eBLBaseComponents">\n' + | ||
' <Ack>Failure</Ack>\n' + | ||
' <Errors>\n' + | ||
' <ShortMessage>Something went wrong.</ShortMessage>\n' + | ||
' <LongMessage>Something really went wrong.</LongMessage>\n' + | ||
' <ErrorCode>' + errorCode + '</ErrorCode>\n' + | ||
' <SeverityCode>Error</SeverityCode>\n' + | ||
' <ErrorClassification>' + errorClassification + '</ErrorClassification>\n' + | ||
' </Errors>' + | ||
'</GetOrdersResponse>' // (not comprehensive) | ||
}); | ||
}); | ||
}; | ||
} | ||
describe('RequestError from response', function() { | ||
beforeEach('stub request', function() { | ||
this.sinon.stub(request, 'post', _buildResponseCallback('12345', 'RequestError')); | ||
}); | ||
beforeEach('simulate request', function (done) { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrders' | ||
}, function(_err, _data) { | ||
err = _err; | ||
data = _data; | ||
done(); | ||
}); | ||
}); | ||
it('throws an EbayRequestError', function() { | ||
expect(err).to.be.an.instanceOf(ebay.EbayRequestError); | ||
}); | ||
it('also gets response data', function() { | ||
expect(data).to.be.ok; | ||
expect(data).to.have.property('Ack', 'Failure'); | ||
}) | ||
}); | ||
describe('SystemError from response', function() { | ||
beforeEach('stub request', function() { | ||
this.sinon.stub(request, 'post', _buildResponseCallback('12345', 'SystemError')); | ||
}); | ||
beforeEach('simulate request', function (done) { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrders' | ||
}, function(_err, _data) { | ||
err = _err; | ||
data = _data; | ||
done(); | ||
}); | ||
}); | ||
it('throws an EbaySystemError', function() { | ||
expect(err).to.be.an.instanceOf(ebay.EbaySystemError); | ||
}); | ||
}); | ||
describe('XML parsing fails', function() { | ||
beforeEach('stub request', function() { | ||
this.sinon.stub(request, 'post', _buildResponseCallback('<<<<', '>>>>')); // screw up XML body | ||
}); | ||
beforeEach('simulate request', function (done) { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrders' | ||
}, function(_err, _data) { | ||
err = _err; | ||
data = _data; | ||
done(); | ||
}); | ||
}); | ||
it('throws an EbayClientError', function() { | ||
expect(err).to.be.an.instanceOf(ebay.EbayClientError); | ||
}) | ||
}); | ||
describe('non-200 response code', function() { | ||
beforeEach('stub request', function () { | ||
this.sinon.stub(request, 'post', function (options, callback) { | ||
process.nextTick(function () { | ||
callback(null, {statusCode: 503}); | ||
}); | ||
}); | ||
}); | ||
beforeEach('simulate request', function (done) { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrders' | ||
}, function(_err) { | ||
err = _err; | ||
done(); | ||
}); | ||
}); | ||
it('throws an EbayClientError', function() { | ||
expect(err).to.be.an.instanceOf(ebay.EbayClientError); | ||
expect(err.message).to.match(/503/); | ||
}) | ||
}); | ||
describe('other client error', function() { | ||
beforeEach('stub request', function () { | ||
this.sinon.stub(request, 'post', function (options, callback) { | ||
process.nextTick(function () { | ||
callback(null, {statusCode: 200, body: ''}); | ||
}); | ||
}); | ||
}); | ||
beforeEach('simulate request', function (done) { | ||
xmlRequest({ | ||
serviceName: 'Trading', | ||
opType: 'GetOrders', | ||
parser: function(data, options, callback) { | ||
callback(new Error("Boo")); | ||
} | ||
}, function(_err) { | ||
err = _err; | ||
done(); | ||
}); | ||
}); | ||
it('throws an EbayClientError', function() { | ||
expect(err).to.be.an.instanceOf(ebay.EbayClientError); | ||
expect(err.message).to.match(/Boo/); | ||
}) | ||
}); | ||
}) | ||
}); | ||
@@ -226,0 +391,0 @@ |
48028
1158
153