From b778b314fbf4379bf840c481e648ba800340a04c Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Wed, 2 Mar 2016 18:20:02 -0800 Subject: [PATCH 1/3] Flatten custom operations in request.object in afterSave hooks. --- spec/ParseAPI.spec.js | 40 ++++++++++++++++++++++++++++++++++++++++ src/RestWrite.js | 14 ++++++++------ 2 files changed, 48 insertions(+), 6 deletions(-) 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..1914f6c8 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -821,17 +821,19 @@ RestWrite.prototype.runAfterTrigger = function() { 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. From c4aac335e04d2d109c1d112369e771370cb0fbc8 Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Wed, 2 Mar 2016 18:23:00 -0800 Subject: [PATCH 2/3] Don't run any afterSave hooks if none are registered. --- src/RestWrite.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/RestWrite.js b/src/RestWrite.js index 1914f6c8..a907a61c 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -816,6 +816,15 @@ 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; From 358a7ae7f325324ee82abd6d901ebaaeadb75e6b Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Wed, 2 Mar 2016 18:38:24 -0800 Subject: [PATCH 3/3] Fix missing 'let/var' in OneSignalPushAdapter.spec. --- spec/OneSignalPushAdapter.spec.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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'},