Skip to content

Commit cdee877

Browse files
authored
Merge pull request #86 from jonathanstokes/item-save-error-handling-fix
Fix for item.save() never calling its callback function
2 parents ac7f51b + 984b637 commit cdee877

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

lib/CollectionItem.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
this.save = function(saveCallback) {
2525
restHandlers.editItem(data.id, kind, changedData, function (error, data, additionalData, req, res) {
26-
var collectionItems = wrapCollectionItems([data], kind, options);
26+
var collectionItems = wrapCollectionItems(data ? [data] : data, kind, options);
2727
saveCallback(error, collectionItems[0], additionalData, req, res);
2828
});
2929

@@ -41,14 +41,14 @@
4141

4242
this.merge = function (withId, callback) {
4343
return restHandlers.mergeItem(data.id, withId, kind, function (error, data, additionalData, req, res) {
44-
var collectionItems = wrapCollectionItems([data], kind, options);
44+
var collectionItems = wrapCollectionItems(data ? [data] : data, kind, options);
4545
callback(error, collectionItems[0], additionalData, req, res);
4646
});
4747
};
4848

4949
this.duplicate = function (callback) {
5050
return restHandlers.duplicateItem(data.id, kind, function (error, data, additionalData, req, res) {
51-
var collectionItems = wrapCollectionItems([data], kind, options);
51+
var collectionItems = wrapCollectionItems(data ? [data] : data, kind, options);
5252
callback(error, collectionItems[0], additionalData, req, res);
5353
});
5454
};

test/unit/CollectionItem.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('CollectionItem', function () {
1010
var restHandlersPath = path.normalize(__dirname + '/../../lib/restHandlers');
1111

1212
var restHandlerMock = {
13-
editItem: sinon.spy(),
13+
editItem: sinon.stub(),
1414
listItems: sinon.spy()
1515
};
1616

@@ -23,6 +23,7 @@ describe('CollectionItem', function () {
2323
var CollectionItem = proxyquire('./../../lib/CollectionItem', stubs);
2424

2525
item = new CollectionItem('deals', {
26+
id: 1,
2627
title: 'Deal title'
2728
}, 1);
2829

@@ -64,4 +65,48 @@ describe('CollectionItem', function () {
6465
sinon.assert.calledWith(restHandlerMock.editItem, 2, 'deals/1/products', {id: 2});
6566
});
6667
});
68+
69+
describe('item.save()', function() {
70+
it('should call restHandler.editItem()', function () {
71+
// In the normal case, we can set a field value and call save(). Internally, the restHandler.editItem()
72+
// method will be called with our update.
73+
item.set('title', 'Other deal title');
74+
item.save();
75+
76+
sinon.assert.calledWith(restHandlerMock.editItem, 1, 'deals', {title: 'Other deal title'});
77+
});
78+
79+
it('should handle error with null data from REST call', function () {
80+
// Set a field to a field ID that doesn't exist (maybe the custom field key is bad).
81+
item.set('badFieldId', 'Ignored value');
82+
83+
// When we save the item in this state, the real RestHandler.editItem() is given bad input, so it receives
84+
// back an error response, such as a 400 with body:
85+
// {
86+
// "success":false,
87+
// "error":"Bad request",
88+
// "error_info":"Please check developers.pipedrive.com for more information about Pipedrive API.",
89+
// "data":null,
90+
// "additional_data":null
91+
// }
92+
//
93+
// We want to emulate this behavior to make sure our CollectionItem callback handles it properly. When a
94+
// item.save(callbackFn) call is made, the callbackFn should have the opportunity to handle this error.
95+
var restError = new Error('Pipedrive API error:Bad request');
96+
restHandlerMock.editItem.callsFake(function(id, kind, changedData, callbackFn) {
97+
callbackFn(restError, null, null);
98+
});
99+
100+
// For purposes of this test, we don't need to do anything in our callback, but we MUST ensure that we get
101+
// called back. Without getting the error object passed to it, we can't respond to the rejected input.
102+
var saveCallback = sinon.spy();
103+
item.save(saveCallback);
104+
105+
sinon.assert.calledWith(restHandlerMock.editItem, 1, 'deals', {'badFieldId': 'Ignored value'});
106+
sinon.assert.calledOnce(saveCallback);
107+
sinon.assert.calledWith(saveCallback, restError);
108+
109+
restHandlerMock.editItem.resetBehavior();
110+
});
111+
});
67112
});

0 commit comments

Comments
 (0)