Skip to content

Properly handle return values in beforeSave #5228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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