Skip to content

Commit

Permalink
Properly handle return values in beforeSave (parse-community#5228)
Browse files Browse the repository at this point in the history
* added failing test case to CloudCode.spec.js

a possible bug found where beforeSave does not apply changes to request
object if the beforeSave hook ends with 'true' returned

* moddified triggers to return null when beforeSave
also changed test cases to be more descriptive + added extra test case that returns promise in the beforeSave

* address original issue

* Revert "address original issue"

This reverts commit e01c57d.

* fix promises and tests

* Add a test to verify that a failed beforeChange hook will
prevent updating the object.
  • Loading branch information
blastoy authored and dplewis committed Mar 14, 2019
1 parent 118e80f commit 7c772c4
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
60 changes: 60 additions & 0 deletions spec/CloudCode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,27 @@ describe('Cloud Code', () => {
);
});

it("test beforeSave changed object fail doesn't change object", async function() {
Parse.Cloud.beforeSave('BeforeSaveChanged', function(req) {
if (req.object.has('fail')) {
return Promise.reject(new Error('something went wrong'));
}

return Promise.resolve();
});

const obj = new Parse.Object('BeforeSaveChanged');
obj.set('foo', 'bar');
await obj.save();
obj.set('foo', 'baz').set('fail', true);
try {
await obj.save();
} catch (e) {
await obj.fetch();
expect(obj.get('foo')).toBe('bar');
}
});

it('test beforeSave returns value on create and update', done => {
Parse.Cloud.beforeSave('BeforeSaveChanged', function(req) {
req.object.set('foo', 'baz');
Expand All @@ -179,6 +200,45 @@ describe('Cloud Code', () => {
});
});

it('test beforeSave applies changes when beforeSave returns true', done => {
Parse.Cloud.beforeSave('Insurance', function(req) {
req.object.set('rate', '$49.99/Month');
return true;
});

const insurance = new Parse.Object('Insurance');
insurance.set('rate', '$5.00/Month');
insurance.save().then(insurance => {
expect(insurance.get('rate')).toEqual('$49.99/Month');
done();
});
});

it('test beforeSave applies changes and resolves returned promise', done => {
Parse.Cloud.beforeSave('Insurance', function(req) {
req.object.set('rate', '$49.99/Month');
return new Parse.Query('Pet').get(req.object.get('pet').id).then(pet => {
pet.set('healthy', true);
return pet.save();
});
});

const pet = new Parse.Object('Pet');
pet.set('healthy', false);
pet.save().then(pet => {
const insurance = new Parse.Object('Insurance');
insurance.set('pet', pet);
insurance.set('rate', '$5.00/Month');
insurance.save().then(insurance => {
expect(insurance.get('rate')).toEqual('$49.99/Month');
new Parse.Query('Pet').get(insurance.get('pet').id).then(pet => {
expect(pet.get('healthy')).toEqual(true);
done();
});
});
});
});

it('test afterSave ran and created an object', function(done) {
Parse.Cloud.afterSave('AfterSaveTest', function(req) {
const obj = new Parse.Object('AfterSaveProof');
Expand Down
2 changes: 1 addition & 1 deletion spec/CloudCodeLogger.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ describe('Cloud Code Logger', () => {
expect(cloudTriggerMessage[0]).toBe('info');
expect(cloudTriggerMessage[2].triggerType).toEqual('beforeSave');
expect(cloudTriggerMessage[1]).toMatch(
/beforeSave triggered for MyObject for user [^ ]*\n {2}Input: {}\n {2}Result: {}/
/beforeSave triggered for MyObject for user [^ ]*\n {2}Input: {}\n {2}Result: {"object":{}}/
);
expect(cloudTriggerMessage[2].user).toBe(user.id);
expect(errorMessage[0]).toBe('error');
Expand Down
15 changes: 15 additions & 0 deletions src/triggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ export function getResponseObject(request, resolve, reject) {
// Use the JSON response
if (
response &&
typeof response === 'object' &&
!request.object.equals(response) &&
request.triggerName === Types.beforeSave
) {
Expand Down Expand Up @@ -573,6 +574,20 @@ export function maybeRunTrigger(
auth
);
}
// beforeSave is expected to return null (nothing)
if (triggerType === Types.beforeSave) {
if (promise && typeof promise.then === 'function') {
return promise.then(response => {
// response.object may come from express routing before hook
if (response && response.object) {
return response;
}
return null;
});
}
return null;
}

return promise;
})
.then(success, error);
Expand Down

0 comments on commit 7c772c4

Please sign in to comment.