diff --git a/src/parse-mockdb.js b/src/parse-mockdb.js index 36cda05..2c20496 100644 --- a/src/parse-mockdb.js +++ b/src/parse-mockdb.js @@ -74,10 +74,24 @@ function runHook(className, hookType, data) { var modelData = Object.assign(new Object, data, {className}); var model = Parse.Object.fromJSON(_.omit(modelData, "ACL")); - return hook.bind(model)().then((result) => { - debugPrint('HOOK', { result }); - var newData = _.cloneDeep(result.toJSON()); - return Parse.Promise.as(_.omit(newData, "ACL")); + // TODO Stub out Parse.Cloud.useMasterKey() so that we can report the correct 'master' + // value here. + var beforeSaveOrBeforeDeleteRequestObject = { + installationId: 'parse-mockdb', + master: false, + object: model, + user: "ParseMockDB doesn't define request.user." + }; + + return hook(beforeSaveOrBeforeDeleteRequestObject).then((beforeSaveOverrideValue) => { + debugPrint('HOOK', { beforeSaveOverrideValue }); + + // Unlike BeforeDeleteResponse, BeforeSaveResponse might specify + var objectToProceedWith = hookType === 'beforeSave' && beforeSaveOverrideValue + ? _.cloneDeep(beforeSaveOverrideValue.toJSON()) + : model; + + return Parse.Promise.as(_.omit(objectToProceedWith, "ACL")); }, (error) => { debugPrint('HOOK', { error }); return Parse.Promise.error(error); @@ -323,8 +337,10 @@ function handleDeleteRequest(request) { const collection = getCollection(request.className); var objToDelete = collection[request.objectId]; - delete collection[request.objectId] - return Parse.Promise.as(respond(200, {})); + return runHook(request.className, 'beforeDelete', objToDelete).then(result => { + delete collection[request.objectId]; + return Parse.Promise.as(respond(200, {})); + }); } function makePointer(className, id) { diff --git a/test/test.js b/test/test.js index 4302765..d78bda9 100644 --- a/test/test.js +++ b/test/test.js @@ -783,26 +783,27 @@ describe('ParseMock', function(){ */ context('when object has beforeSave hook registered', function() { - function beforeSave() { - if (this.get("error")) { + + function beforeSavePromise(request) { + var brand = request.object; + if (brand.get("error")) { return Parse.Promise.error("whoah"); } - this.set('cool', true); - return Parse.Promise.as(this); + brand.set('cool', true); + return Parse.Promise.as(brand); } it('runs the hook before saving the model and persists the object', function() { - ParseMockDB.registerHook('Brand', 'beforeSave', beforeSave); + ParseMockDB.registerHook('Brand', 'beforeSave', beforeSavePromise); var brand = new Brand(); assert(!brand.has('cool')); - brand.save().then(savedBrand => { + brand.save().then(function (savedBrand) { assert(savedBrand.has('cool')); assert(savedBrand.get('cool')); - var q = new Parse.Query(Brand); - q.first().then(queriedBrand => { + new Parse.Query(Brand).first().then(function (queriedBrand) { assert(queriedBrand.has('cool')); assert(queriedBrand.get('cool')); }); @@ -810,17 +811,67 @@ describe('ParseMock', function(){ }) it('rejects the save if there is a problem', function(done) { - ParseMockDB.registerHook('Brand', 'beforeSave', beforeSave); + ParseMockDB.registerHook('Brand', 'beforeSave', beforeSavePromise); var brand = new Brand({error: true}); - brand.save().then(savedBrand => { + brand.save().then(function (savedBrand) { throw new Error("should not have saved") - }, error => { + }, function(error) { assert.equal(error, "whoah"); done(); }); - }) - }) + }); + }); + + context('when object has beforeDelete hook registered', function() { + + var beforeDeleteWasRun; + + beforeEach(function () { + beforeDeleteWasRun = false; + }); + + function beforeDeletePromise(request) { + var brand = request.object; + if (brand.get("error")) { + return Parse.Promise.error("whoah"); + } + beforeDeleteWasRun = true; + return Parse.Promise.as(); + } + + it('runs the hook before deleting the object', function() { + ParseMockDB.registerHook('Brand', 'beforeDelete', beforeDeletePromise); + + createBrandP().done(function (savedBrand) { + return Parse.Object.destroyAll([savedBrand]); + }).done(function () { + assert(beforeDeleteWasRun); + }); + + new Parse.Query(Brand).find().done(function (results) { + assert.equal(results.length, 0); + }); + }); + + it('rejects the delete if there is a problem', function(done) { + ParseMockDB.registerHook('Brand', 'beforeDelete', beforeDeletePromise); + + var brand = new Brand({error: true}); + brand.save().done(function (savedBrand) { + return Parse.Object.destroyAll([savedBrand]); + }).then(function (deletedBrand) { + throw new Error("should not have deleted") + }, function(error) { + assert.equal(error, "whoah"); + return new Parse.Query(Brand).find(); + }).done(function(results) { + assert.equal(results.length, 1); + done(); + }); + }); + + }); });