diff --git a/spec/OneSignalPushAdapter.spec.js b/spec/OneSignalPushAdapter.spec.js index a9b853d9..77b958c5 100644 --- a/spec/OneSignalPushAdapter.spec.js +++ b/spec/OneSignalPushAdapter.spec.js @@ -1,3 +1,4 @@ +'use strict'; var OneSignalPushAdapter = require('../src/Adapters/Push/OneSignalPushAdapter'); var classifyInstallations = require('../src/Adapters/Push/PushAdapterUtils').classifyInstallations; @@ -210,7 +211,7 @@ describe('OneSignalPushAdapter', () => { expect(write).toHaveBeenCalled(); // iOS - args = write.calls.first().args; + let args = write.calls.first().args; expect(args[0]).toEqual(JSON.stringify({ 'contents': { 'en':'Example content'}, 'content_available':true, @@ -219,7 +220,7 @@ describe('OneSignalPushAdapter', () => { 'app_id':'APP ID' })); - // Android + // Android args = write.calls.mostRecent().args; expect(args[0]).toEqual(JSON.stringify({ 'contents': { 'en':'Example content'}, diff --git a/spec/ParseAPI.spec.js b/spec/ParseAPI.spec.js index 76fe2a35..17bfc73b 100644 --- a/spec/ParseAPI.spec.js +++ b/spec/ParseAPI.spec.js @@ -692,6 +692,46 @@ describe('miscellaneous', function() { }); }); + it('afterSave flattens custom operations', done => { + var triggerTime = 0; + // Register a mock beforeSave hook + Parse.Cloud.afterSave('GameScore', function(req, res) { + let object = req.object; + expect(object instanceof Parse.Object).toBeTruthy(); + let originalObject = req.original; + if (triggerTime == 0) { + // Create + expect(object.get('yolo')).toEqual(1); + } else if (triggerTime == 1) { + // Update + expect(object.get('yolo')).toEqual(2); + // Check the originalObject + expect(originalObject.get('yolo')).toEqual(1); + } else { + res.error(); + } + triggerTime++; + res.success(); + }); + + var obj = new Parse.Object('GameScore'); + obj.increment('yolo', 1); + obj.save().then(() => { + obj.increment('yolo', 1); + return obj.save(); + }).then(() => { + // Make sure the checking has been triggered + expect(triggerTime).toBe(2); + // Clear mock afterSave + Parse.Cloud._removeHook("Triggers", "afterSave", "GameScore"); + done(); + }, error => { + console.error(error); + fail(error); + done(); + }); + }); + it('test cloud function error handling', (done) => { // Register a function which will fail Parse.Cloud.define('willFail', (req, res) => { diff --git a/src/RestWrite.js b/src/RestWrite.js index bfc6477f..a907a61c 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -816,22 +816,33 @@ RestWrite.prototype.runDatabaseOperation = function() { // Returns nothing - doesn't wait for the trigger. RestWrite.prototype.runAfterTrigger = function() { + if (!this.response || !this.response.response) { + return; + } + + // Avoid doing any setup for triggers if there is no 'afterSave' trigger for this class. + if (!triggers.triggerExists(this.className, triggers.Types.afterSave, this.config.applicationId)) { + return Promise.resolve(); + } + var extraData = {className: this.className}; if (this.query && this.query.objectId) { extraData.objectId = this.query.objectId; } - // Build the inflated object, different from beforeSave, originalData is not empty - // since developers can change data in the beforeSave. - var inflatedObject = triggers.inflate(extraData, this.originalData); - inflatedObject._finishFetch(this.data); // Build the original object, we only do this for a update write. - var originalObject; + let originalObject; if (this.query && this.query.objectId) { originalObject = triggers.inflate(extraData, this.originalData); } - triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, inflatedObject, originalObject, this.config.applicationId); + // Build the inflated object, different from beforeSave, originalData is not empty + // since developers can change data in the beforeSave. + let updatedObject = triggers.inflate(extraData, this.originalData); + updatedObject.set(Parse._decode(undefined, this.data)); + updatedObject._handleSaveResponse(this.response.response, this.response.status || 200); + + triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config.applicationId); }; // A helper to figure out what location this operation happens at.