From 85c9dc4909c77a06d24a5ef67e5430da37c2ac42 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 17:49:26 +0000 Subject: [PATCH 01/16] Make the test fail by adding a request object. --- test/test.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/test.js b/test/test.js index 4302765..1afaf33 100644 --- a/test/test.js +++ b/test/test.js @@ -783,12 +783,14 @@ describe('ParseMock', function(){ */ context('when object has beforeSave hook registered', function() { - function beforeSave() { - if (this.get("error")) { + + function beforeSave(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() { From 1ebe61281628bc0e00eb16f7b569c5f0919f9ae7 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 17:53:35 +0000 Subject: [PATCH 02/16] Pass in the request object into the beforeSave handler. --- src/parse-mockdb.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/parse-mockdb.js b/src/parse-mockdb.js index 36cda05..7dff950 100644 --- a/src/parse-mockdb.js +++ b/src/parse-mockdb.js @@ -74,7 +74,16 @@ 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) => { + // TODO Stub out Parse.Cloud.useMasterKey() so that we can report the correct 'master' + // value here. + var beforeSaveRequest = { + installationId: 'parse-mockdb', + master: false, + object: model, + user: "ParseMockDB doesn't define request.user." + }; + + return hook(beforeSaveRequest).then((result) => { debugPrint('HOOK', { result }); var newData = _.cloneDeep(result.toJSON()); return Parse.Promise.as(_.omit(newData, "ACL")); From 5cc80bf1576ac0e2b854679ecb6a526c1bacb054 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 17:54:19 +0000 Subject: [PATCH 03/16] Rename variable. --- test/test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index 1afaf33..b501a21 100644 --- a/test/test.js +++ b/test/test.js @@ -784,7 +784,7 @@ describe('ParseMock', function(){ context('when object has beforeSave hook registered', function() { - function beforeSave(request) { + function beforeSavePromise(request) { var brand = request.object; if (brand.get("error")) { return Parse.Promise.error("whoah"); @@ -794,7 +794,7 @@ describe('ParseMock', function(){ } 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')); @@ -812,7 +812,7 @@ 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}); From 1e677683e913796e04b709a63a9571ea82b28fa0 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 18:18:32 +0000 Subject: [PATCH 04/16] Rename request. --- src/parse-mockdb.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parse-mockdb.js b/src/parse-mockdb.js index 7dff950..10e7c51 100644 --- a/src/parse-mockdb.js +++ b/src/parse-mockdb.js @@ -76,14 +76,14 @@ function runHook(className, hookType, data) { // TODO Stub out Parse.Cloud.useMasterKey() so that we can report the correct 'master' // value here. - var beforeSaveRequest = { + var beforeSaveOrBeforeDeleteRequestObject = { installationId: 'parse-mockdb', master: false, object: model, user: "ParseMockDB doesn't define request.user." }; - return hook(beforeSaveRequest).then((result) => { + return hook(beforeSaveOrBeforeDeleteRequestObject).then((result) => { debugPrint('HOOK', { result }); var newData = _.cloneDeep(result.toJSON()); return Parse.Promise.as(_.omit(newData, "ACL")); From d60a302719162d75cf7d8c1df7bbccf26b7c7483 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 18:35:32 +0000 Subject: [PATCH 05/16] Add failing test for beforeDelete. --- test/test.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/test.js b/test/test.js index b501a21..ac2d14e 100644 --- a/test/test.js +++ b/test/test.js @@ -825,4 +825,48 @@ describe('ParseMock', function(){ }) }) + 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"); + } + return Parse.Promise.as(brand); + } + + it('runs the hook before deleting the object', function() { + ParseMockDB.registerHook('Brand', 'beforeDelete', beforeDeletePromise); + + var brand = new Brand(); + brand.save().done(function (savedBrand) { + return Parse.Object.destroyAll([savedBrand]); + }).done(function () { + assert(beforeDeleteWasRun); + }); + + // TODO Assert that no brands should exist in the backend. + }); + + it('rejects the delete if there is a problem', function(done) { + ParseMockDB.registerHook('Brand', 'beforeDelete', beforeDeletePromise); + + var brand = new Brand({error: true}); + + brand.save().then(savedBrand => { + throw new Error("should not have saved") + }, error => { + assert.equal(error, "whoah"); + done(); + }); + }); + + }); + }); From 81ef2aa7eed3c63c60121a1687b1a7e11b0f8640 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 18:42:33 +0000 Subject: [PATCH 06/16] Fix test by switching the flag. --- test/test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test.js b/test/test.js index ac2d14e..6a127fe 100644 --- a/test/test.js +++ b/test/test.js @@ -838,6 +838,7 @@ describe('ParseMock', function(){ if (brand.get("error")) { return Parse.Promise.error("whoah"); } + beforeDeleteWasRun = true; return Parse.Promise.as(brand); } From 5ef0d1365e164d6bd3e22910aac27d0a2f5fe416 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 18:44:47 +0000 Subject: [PATCH 07/16] Fail test again by not defining a return value. --- test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index 6a127fe..24801fe 100644 --- a/test/test.js +++ b/test/test.js @@ -839,7 +839,7 @@ describe('ParseMock', function(){ return Parse.Promise.error("whoah"); } beforeDeleteWasRun = true; - return Parse.Promise.as(brand); + return Parse.Promise.as(); } it('runs the hook before deleting the object', function() { From 31ea8609bbd076f9246158355b318716130befd6 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 18:51:45 +0000 Subject: [PATCH 08/16] Reason about beforeSave override value. --- src/parse-mockdb.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/parse-mockdb.js b/src/parse-mockdb.js index 10e7c51..2c20496 100644 --- a/src/parse-mockdb.js +++ b/src/parse-mockdb.js @@ -83,10 +83,15 @@ function runHook(className, hookType, data) { user: "ParseMockDB doesn't define request.user." }; - return hook(beforeSaveOrBeforeDeleteRequestObject).then((result) => { - debugPrint('HOOK', { result }); - var newData = _.cloneDeep(result.toJSON()); - return Parse.Promise.as(_.omit(newData, "ACL")); + 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); @@ -332,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) { From 58a150a380d9f9755c41b20d1a90124c940c57c5 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:28:01 +0000 Subject: [PATCH 09/16] Fix test by performing deletion. --- test/test.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index 24801fe..47fb53b 100644 --- a/test/test.js +++ b/test/test.js @@ -859,9 +859,10 @@ describe('ParseMock', function(){ ParseMockDB.registerHook('Brand', 'beforeDelete', beforeDeletePromise); var brand = new Brand({error: true}); - - brand.save().then(savedBrand => { - throw new Error("should not have saved") + brand.save().done(function (savedBrand) { + return Parse.Object.destroyAll([savedBrand]); + }).then(deletedBrand => { + throw new Error("should not have deleted") }, error => { assert.equal(error, "whoah"); done(); From 0133794ee2af8269b6fbbd873d9c35228d0a0088 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:30:24 +0000 Subject: [PATCH 10/16] Simplify creation of Brand. --- test/test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 47fb53b..d912b48 100644 --- a/test/test.js +++ b/test/test.js @@ -845,8 +845,7 @@ describe('ParseMock', function(){ it('runs the hook before deleting the object', function() { ParseMockDB.registerHook('Brand', 'beforeDelete', beforeDeletePromise); - var brand = new Brand(); - brand.save().done(function (savedBrand) { + createBrandP().done(function (savedBrand) { return Parse.Object.destroyAll([savedBrand]); }).done(function () { assert(beforeDeleteWasRun); From c9c078272ad815f1bce7d9a5da9547bac3768587 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:33:04 +0000 Subject: [PATCH 11/16] Remove TODO by adding assertion for empty collection. --- test/test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index d912b48..484e25d 100644 --- a/test/test.js +++ b/test/test.js @@ -851,7 +851,10 @@ describe('ParseMock', function(){ assert(beforeDeleteWasRun); }); - // TODO Assert that no brands should exist in the backend. + var q = new Parse.Query(Brand); + q.find().done(results => { + assert(results.length === 0); + }); }); it('rejects the delete if there is a problem', function(done) { From f9a55b3ef649db97a674105f2c7dbaa2ed683441 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:37:16 +0000 Subject: [PATCH 12/16] Add assertions for the state of the mock collection. --- test/test.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index 484e25d..51dd0e6 100644 --- a/test/test.js +++ b/test/test.js @@ -851,9 +851,8 @@ describe('ParseMock', function(){ assert(beforeDeleteWasRun); }); - var q = new Parse.Query(Brand); - q.find().done(results => { - assert(results.length === 0); + new Parse.Query(Brand).find().done(results => { + assert.equal(results.length, 0); }); }); @@ -867,6 +866,10 @@ describe('ParseMock', function(){ throw new Error("should not have deleted") }, error => { assert.equal(error, "whoah"); + + return new Parse.Query(Brand).find(); + }).done(results => { + assert.equal(results.length, 1); done(); }); }); From 197eadfde92be8f461a5f5ca6ce4642b1b089734 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:42:12 +0000 Subject: [PATCH 13/16] Fix semicolons. --- test/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 51dd0e6..ca724dd 100644 --- a/test/test.js +++ b/test/test.js @@ -822,8 +822,8 @@ describe('ParseMock', function(){ assert.equal(error, "whoah"); done(); }); - }) - }) + }); + }); context('when object has beforeDelete hook registered', function() { From 1ba2162ff8039b18e707cf5316ea99494e3a7f14 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:43:48 +0000 Subject: [PATCH 14/16] Replace => syntax with function() syntax. --- test/test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test.js b/test/test.js index ca724dd..1df0b48 100644 --- a/test/test.js +++ b/test/test.js @@ -799,12 +799,12 @@ describe('ParseMock', function(){ 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 => { + q.first().then(function (queriedBrand) { assert(queriedBrand.has('cool')); assert(queriedBrand.get('cool')); }); @@ -816,9 +816,9 @@ describe('ParseMock', function(){ 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(); }); @@ -851,7 +851,7 @@ describe('ParseMock', function(){ assert(beforeDeleteWasRun); }); - new Parse.Query(Brand).find().done(results => { + new Parse.Query(Brand).find().done(function (results) { assert.equal(results.length, 0); }); }); @@ -862,13 +862,13 @@ describe('ParseMock', function(){ var brand = new Brand({error: true}); brand.save().done(function (savedBrand) { return Parse.Object.destroyAll([savedBrand]); - }).then(deletedBrand => { + }).then(function (deletedBrand) { throw new Error("should not have deleted") - }, error => { + }, function(error) { assert.equal(error, "whoah"); return new Parse.Query(Brand).find(); - }).done(results => { + }).done(function(results) { assert.equal(results.length, 1); done(); }); From aad0ce9d6a06702ef1d55e185c0fcbe6fa31ad57 Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:44:30 +0000 Subject: [PATCH 15/16] Inline variable. --- test/test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test.js b/test/test.js index 1df0b48..d577e6f 100644 --- a/test/test.js +++ b/test/test.js @@ -803,8 +803,7 @@ describe('ParseMock', function(){ assert(savedBrand.has('cool')); assert(savedBrand.get('cool')); - var q = new Parse.Query(Brand); - q.first().then(function (queriedBrand) { + new Parse.Query(Brand).first().then(function (queriedBrand) { assert(queriedBrand.has('cool')); assert(queriedBrand.get('cool')); }); From 1dced93a5a42e94914a56d2ca84c328b73236bfa Mon Sep 17 00:00:00 2001 From: Hok Shun Poon Date: Thu, 10 Dec 2015 19:45:30 +0000 Subject: [PATCH 16/16] Remove whitespace. --- test/test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test.js b/test/test.js index d577e6f..d78bda9 100644 --- a/test/test.js +++ b/test/test.js @@ -865,7 +865,6 @@ describe('ParseMock', function(){ 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);