diff --git a/core/js/oc-backbone-webdav.js b/core/js/oc-backbone-webdav.js index 724660ff93a2..0503abea8bda 100644 --- a/core/js/oc-backbone-webdav.js +++ b/core/js/oc-backbone-webdav.js @@ -180,9 +180,25 @@ } function callPropPatch(client, options, model, headers) { + var changes = model.changed; + if (options.wait && _.isEmpty(changes)) { + // usually with "wait" mode, the changes aren't set yet, + changes = options.data; + + // if options.patch is not set, then data contains all the data + // instead of just the properties to patch + if (!options.patch) { + // remove reserved properties + delete changes.href; + delete changes[_.result(model, 'idAttribute')]; + + // note: there is no way to diff with previous values here so + // we just send everything + } + } return client.propPatch( options.url, - convertModelAttributesToDavProperties(model.changed, options.davProperties), + convertModelAttributesToDavProperties(changes, options.davProperties), headers ).then(function(result) { if (result.status === 207 && result.body && result.body.length > 0) { @@ -196,6 +212,11 @@ } if (isSuccessStatus(result.status)) { + // with wait, we set the changes only after success + if (options.wait) { + model.set(changes, options); + } + if (_.isFunction(options.success)) { // pass the object's own values because the server // does not return the updated model @@ -236,7 +257,7 @@ options.type, options.url, headers, - options.data + JSON.stringify(options.data) ).then(function(result) { if (!isSuccessStatus(result.status)) { if (_.isFunction(options.error)) { @@ -353,7 +374,7 @@ // Ensure that we have the appropriate request data. if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { - params.data = JSON.stringify(options.attrs || model.toJSON(options)); + params.data = options.attrs || model.toJSON(options); } // Don't process data on a non-GET request. diff --git a/core/js/tests/specs/oc-backbone-webdavSpec.js b/core/js/tests/specs/oc-backbone-webdavSpec.js index 6df6da4e6161..30b64fbdb5d7 100644 --- a/core/js/tests/specs/oc-backbone-webdavSpec.js +++ b/core/js/tests/specs/oc-backbone-webdavSpec.js @@ -243,97 +243,164 @@ describe('Backbone Webdav extension', function() { }); }); - it('makes a PROPPATCH request to update model', function() { - var model = new TestModel({ - id: '123', - firstName: 'Hello', - lastName: 'World', - age: 32, - married: false - }); + describe('updating', function() { + it('makes a PROPPATCH request to update model', function() { + var model = new TestModel({ + id: '123', + firstName: 'Hello', + lastName: 'World', + age: 32, + married: false + }); - model.save({ - firstName: 'Hey', - age: 33, - married: true + model.save({ + firstName: 'Hey', + age: 33, + married: true + }); + + expect(davClientPropPatchStub.calledOnce).toEqual(true); + expect(davClientPropPatchStub.getCall(0).args[0]) + .toEqual('http://example.com/owncloud/remote.php/test/123'); + expect(davClientPropPatchStub.getCall(0).args[1]) + .toEqual({ + '{http://owncloud.org/ns}first-name': 'Hey', + '{http://owncloud.org/ns}age': '33', + '{http://owncloud.org/ns}married': 'true' + }); + expect(davClientPropPatchStub.getCall(0).args[2]['X-Requested-With']) + .toEqual('XMLHttpRequest'); + + deferredRequest.resolve({ + status: 207, + body: [{ + href: 'http://example.com/owncloud/remote.php/test/123', + propStat: [{ + status: 'HTTP/1.1 200 OK', + properties: { + '{http://owncloud.org/ns}first-name': '', + '{http://owncloud.org/ns}age-name': '', + '{http://owncloud.org/ns}married': '' + } + }] + }] + }); + + expect(model.id).toEqual('123'); + expect(model.get('firstName')).toEqual('Hey'); + expect(model.get('age')).toEqual(33); + expect(model.get('married')).toEqual(true); }); - expect(davClientPropPatchStub.calledOnce).toEqual(true); - expect(davClientPropPatchStub.getCall(0).args[0]) - .toEqual('http://example.com/owncloud/remote.php/test/123'); - expect(davClientPropPatchStub.getCall(0).args[1]) - .toEqual({ - '{http://owncloud.org/ns}first-name': 'Hey', - '{http://owncloud.org/ns}age': '33', - '{http://owncloud.org/ns}married': 'true' + it('calls error callback with status code 422 in case of failed PROPPATCH properties', function() { + var successHandler = sinon.stub(); + var errorHandler = sinon.stub(); + var model = new TestModel({ + id: '123', + firstName: 'Hello', + lastName: 'World', + age: 32, + married: false }); - expect(davClientPropPatchStub.getCall(0).args[2]['X-Requested-With']) - .toEqual('XMLHttpRequest'); - deferredRequest.resolve({ - status: 207, - body: [{ - href: 'http://example.com/owncloud/remote.php/test/123', - propStat: [{ - status: 'HTTP/1.1 200 OK', - properties: { - '{http://owncloud.org/ns}first-name': '', - '{http://owncloud.org/ns}age-name': '', - '{http://owncloud.org/ns}married': '' - } + model.save({ + firstName: 'Hey', + lastName: 'low' + }, { + success: successHandler, + error: errorHandler + }); + + deferredRequest.resolve({ + status: 207, + body: [{ + href: 'http://example.com/owncloud/remote.php/test/123', + propStat: [{ + status: 'HTTP/1.1 200 OK', + properties: { + '{http://owncloud.org/ns}last-name': '' + } + }, { + status: 'HTTP/1.1 403 Forbidden', + properties: { + '{http://owncloud.org/ns}first-name': '' + } + }] }] - }] - }); + }); - expect(model.id).toEqual('123'); - expect(model.get('firstName')).toEqual('Hey'); - expect(model.get('age')).toEqual(33); - expect(model.get('married')).toEqual(true); - }); + expect(davClientPropPatchStub.calledOnce).toEqual(true); - it('calls error callback with status code 422 in case of failed PROPPATCH properties', function() { - var successHandler = sinon.stub(); - var errorHandler = sinon.stub(); - var model = new TestModel({ - id: '123', - firstName: 'Hello', - lastName: 'World', - age: 32, - married: false + expect(successHandler.notCalled).toEqual(true); + expect(errorHandler.calledOnce).toEqual(true); + expect(errorHandler.getCall(0).args[0]).toEqual(model); + expect(errorHandler.getCall(0).args[1].status).toEqual(422); }); - model.save({ - firstName: 'Hey', - lastName: 'low' - }, { - success: successHandler, - error: errorHandler + it('calls error handler if error status in PROPPATCH response', function() { + testMethodError(function(success, error) { + var model = new TestModel(); + model.save({ + firstName: 'Hey' + }, { + success: success, + error: error + }); + }); }); - deferredRequest.resolve({ - status: 207, - body: [{ - href: 'http://example.com/owncloud/remote.php/test/123', - propStat: [{ - status: 'HTTP/1.1 200 OK', - properties: { - '{http://owncloud.org/ns}last-name': '' - } - }, { - status: 'HTTP/1.1 403 Forbidden', - properties: { - '{http://owncloud.org/ns}first-name': '' - } + it('sends all data when using wait flag', function() { + var successHandler = sinon.stub(); + var errorHandler = sinon.stub(); + var model = new TestModel({ + id: '123', + firstName: 'Hello', + lastName: 'World', + age: 32, + married: false + }); + + model.save({ + firstName: 'Hey', + lastName: 'low' + }, { + wait: true, + success: successHandler, + error: errorHandler + }); + + // attributes not updated yet + expect(model.get('firstName')).toEqual('Hello'); + + deferredRequest.resolve({ + status: 207, + body: [{ + href: 'http://example.com/owncloud/remote.php/test/123', + propStat: [{ + status: 'HTTP/1.1 200 OK', + properties: { + '{http://owncloud.org/ns}first-name': '', + '{http://owncloud.org/ns}last-name': '' + } + }] }] - }] - }); + }); - expect(davClientPropPatchStub.calledOnce).toEqual(true); - expect(successHandler.notCalled).toEqual(true); - expect(errorHandler.calledOnce).toEqual(true); - expect(errorHandler.getCall(0).args[0]).toEqual(model); - expect(errorHandler.getCall(0).args[1].status).toEqual(422); + expect(davClientPropPatchStub.calledOnce).toEqual(true); + // just resends everything + expect(davClientPropPatchStub.getCall(0).args[1]) + .toEqual({ + '{http://owncloud.org/ns}first-name': 'Hey', + '{http://owncloud.org/ns}last-name': 'low', + '{http://owncloud.org/ns}age': '32', + '{http://owncloud.org/ns}married': 'false', + }); + + expect(model.get('firstName')).toEqual('Hey'); + expect(successHandler.calledOnce).toEqual(true); + expect(errorHandler.notCalled).toEqual(true); + }); }); it('uses PROPFIND to fetch single model', function() { @@ -429,17 +496,6 @@ describe('Backbone Webdav extension', function() { }); }); }); - it('calls error handler if error status in PROPPATCH response', function() { - testMethodError(function(success, error) { - var model = new TestModel(); - model.save({ - firstName: 'Hey' - }, { - success: success, - error: error - }); - }); - }); });