Skip to content

Commit

Permalink
Merge pull request #28791 from owncloud/stable10-backbone-proppatch-w…
Browse files Browse the repository at this point in the history
…aitmode

[stable10] Make Backbone PROPPATCH work with options.wait mode
  • Loading branch information
Vincent Petry authored Aug 25, 2017
2 parents 72bc588 + 70233a5 commit 7be4577
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 90 deletions.
27 changes: 24 additions & 3 deletions core/js/oc-backbone-webdav.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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.
Expand Down
230 changes: 143 additions & 87 deletions core/js/tests/specs/oc-backbone-webdavSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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
});
});
});
});


Expand Down

0 comments on commit 7be4577

Please sign in to comment.