From 2b90c982f2b50c00fcbb618182251822bfd61c8d Mon Sep 17 00:00:00 2001 From: Yuki Takeichi Date: Wed, 23 Nov 2016 15:49:06 +0900 Subject: [PATCH 1/6] fix broken test --- src/__tests__/ParseObject-test.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 17e539593..b65babdb4 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -22,6 +22,7 @@ jest.dontMock('../ParseGeoPoint'); jest.dontMock('../ParseObject'); jest.dontMock('../ParseOp'); jest.dontMock('../ParsePromise'); +jest.dontMock('../ParseRelation'); jest.dontMock('../RESTController'); jest.dontMock('../SingleInstanceStateController'); jest.dontMock('../TaskQueue'); @@ -34,16 +35,6 @@ jest.dontMock('./test_helpers/mockXHR'); jest.useFakeTimers(); -var mockRelation = function(parent, key) { - this.parentClass = parent.className; - this.parentId = parent.id; - this.key = key; -}; -mockRelation.prototype.add = function(obj) { - this.targetClassName = obj.className; -}; -jest.setMock('../ParseRelation', mockRelation); - var queryResults = []; var mockQuery = function(className) { this.className = className; @@ -465,8 +456,7 @@ describe('ParseObject', () => { 'Called relation() on non-relation field age' ); var rel = o.relation('friends'); - expect(rel.parentClass).toBe('Person'); - expect(rel.parentId).toBe('AA'); + expect(rel.parent).toBe(o); expect(rel.key).toBe('friends'); var friend = new ParseObject('Person'); friend.id = 'BB'; From 9886aed40cd2efad2305dd74181154f319260b23 Mon Sep 17 00:00:00 2001 From: Yuki Takeichi Date: Wed, 23 Nov 2016 16:49:48 +0900 Subject: [PATCH 2/6] Support clone with relation (fix #381) --- src/ParseObject.js | 2 ++ src/ParseOp.js | 2 ++ src/__tests__/ParseObject-test.js | 26 ++++++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/ParseObject.js b/src/ParseObject.js index e5dd6ba83..580f6fe44 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -655,6 +655,8 @@ export default class ParseObject { !(changes[k] instanceof ParseACL) ) { newOps[k] = new SetOp(new ParseACL(changes[k])); + } else if (changes[k] instanceof ParseRelation) { + newOps[k] = new SetOp(new ParseRelation(this, k)); } else { newOps[k] = new SetOp(changes[k]); } diff --git a/src/ParseOp.js b/src/ParseOp.js index b0b0f0b9d..4e2083240 100644 --- a/src/ParseOp.js +++ b/src/ParseOp.js @@ -389,6 +389,8 @@ export class RelationOp extends Op { return this; } else if (previous instanceof UnsetOp) { throw new Error('You cannot modify a relation after deleting it.'); + } else if (previous instanceof SetOp && previous._value instanceof ParseRelation) { + return this; } else if (previous instanceof RelationOp) { if (previous._targetClassName && previous._targetClassName !== this._targetClassName) { diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index b65babdb4..38b13cc58 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -464,6 +464,32 @@ describe('ParseObject', () => { expect(rel.targetClassName).toBe('Person'); }); + it('can be cloned with relation (#381)', () => { + var relationJSON = {__type: "Relation", className: "Foo"}; + var o = ParseObject.fromJSON({ + objectId: '7777777777', + className: 'Foo', + aRelation: relationJSON, + }); + o.relation('aRelation').add(o); + var o2 = o.clone(); + var newRel = o2.relation('aRelation'); + newRel.add(o); + expect(newRel.toJSON()).toEqual(relationJSON); + expect(o2._getSaveJSON()).toEqual({ + aRelation: { + __op: 'AddRelation', + objects: [ + { + __type: 'Pointer', + className: 'Foo', + objectId: '7777777777' + }, + ], + } + }); + }); + it('can detect dirty object children', () => { var o = new ParseObject('Person'); o._finishFetch({ From 57f11e1f0a71d0d69397efc18eb4def60b50052a Mon Sep 17 00:00:00 2001 From: Yuki Takeichi Date: Thu, 24 Nov 2016 01:06:22 +0900 Subject: [PATCH 3/6] fix bug --- src/ParseObject.js | 4 +++- src/__tests__/ParseObject-test.js | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ParseObject.js b/src/ParseObject.js index 580f6fe44..751e6d651 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -656,7 +656,9 @@ export default class ParseObject { ) { newOps[k] = new SetOp(new ParseACL(changes[k])); } else if (changes[k] instanceof ParseRelation) { - newOps[k] = new SetOp(new ParseRelation(this, k)); + var relation = new ParseRelation(this, k); + relation.targetClassName = this.className; + newOps[k] = new SetOp(relation); } else { newOps[k] = new SetOp(changes[k]); } diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 38b13cc58..801fed884 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -473,6 +473,12 @@ describe('ParseObject', () => { }); o.relation('aRelation').add(o); var o2 = o.clone(); + expect(o2._getSaveJSON()).toEqual({ + aRelation: { + __type: 'Relation', + className: 'Foo', + }, + }); var newRel = o2.relation('aRelation'); newRel.add(o); expect(newRel.toJSON()).toEqual(relationJSON); @@ -486,7 +492,7 @@ describe('ParseObject', () => { objectId: '7777777777' }, ], - } + }, }); }); From 2899a7399486afa03ae94a6986aed596ed4f6b0d Mon Sep 17 00:00:00 2001 From: Yuki Takeichi Date: Thu, 24 Nov 2016 01:25:01 +0900 Subject: [PATCH 4/6] fix bug --- src/ParseObject.js | 2 +- src/__tests__/ParseObject-test.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ParseObject.js b/src/ParseObject.js index 751e6d651..7a50f516d 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -657,7 +657,7 @@ export default class ParseObject { newOps[k] = new SetOp(new ParseACL(changes[k])); } else if (changes[k] instanceof ParseRelation) { var relation = new ParseRelation(this, k); - relation.targetClassName = this.className; + relation.targetClassName = changes[k].targetClassName; newOps[k] = new SetOp(relation); } else { newOps[k] = new SetOp(changes[k]); diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 801fed884..1f8c73035 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -465,22 +465,22 @@ describe('ParseObject', () => { }); it('can be cloned with relation (#381)', () => { - var relationJSON = {__type: "Relation", className: "Foo"}; + var relationJSON = {__type: 'Relation', className: 'Bar'}; var o = ParseObject.fromJSON({ objectId: '7777777777', className: 'Foo', aRelation: relationJSON, }); - o.relation('aRelation').add(o); var o2 = o.clone(); expect(o2._getSaveJSON()).toEqual({ - aRelation: { - __type: 'Relation', - className: 'Foo', - }, + aRelation: relationJSON, }); var newRel = o2.relation('aRelation'); - newRel.add(o); + var bar = ParseObject.fromJSON({ + objectId: '8888888888', + className: 'Bar', + }); + newRel.add(bar); expect(newRel.toJSON()).toEqual(relationJSON); expect(o2._getSaveJSON()).toEqual({ aRelation: { @@ -488,8 +488,8 @@ describe('ParseObject', () => { objects: [ { __type: 'Pointer', - className: 'Foo', - objectId: '7777777777' + className: 'Bar', + objectId: '8888888888' }, ], }, From 6a20851bcc5ce84098e211b1f70f0a0eabd38044 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Sat, 1 Dec 2018 16:35:07 -0600 Subject: [PATCH 5/6] test fix --- integration/test/ParseObjectTest.js | 14 ++++++ src/ParseOp.js | 2 - src/__tests__/ParseObject-test.js | 68 +++++++++++++++++------------ 3 files changed, 55 insertions(+), 29 deletions(-) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index 0941bd229..a811dd403 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -1455,4 +1455,18 @@ describe('Parse Object', () => { done(); } }); + + it('can clone with relation', (done) => { + const o = Parse.Object.fromJSON({ + objectId: '7777777777', + className: 'Foo', + aRelation: { __type: 'Relation', className: 'Foo' }, + }); + const o2 = o.clone(); + assert.equal( + o.relation('aRelation').targetClassName, + o2.relation('aRelation').targetClassName + ); + done(); + }); }); diff --git a/src/ParseOp.js b/src/ParseOp.js index 91f7a9c16..4736897dc 100644 --- a/src/ParseOp.js +++ b/src/ParseOp.js @@ -392,8 +392,6 @@ export class RelationOp extends Op { return this; } else if (previous instanceof UnsetOp) { throw new Error('You cannot modify a relation after deleting it.'); - } else if (previous instanceof SetOp && previous._value instanceof ParseRelation) { - return this; } else if (previous instanceof RelationOp) { if (previous._targetClassName && previous._targetClassName !== this._targetClassName) { diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index c30bd5a06..b937b55f2 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -36,13 +36,48 @@ jest.dontMock('./test_helpers/mockXHR'); jest.useFakeTimers(); const mockRelation = function(parent, key) { - this.parentClass = parent.className; - this.parentId = parent.id; + // The parent and key fields will be populated by the parent + if (parent) { + this.parentClass = parent.className; + this.parentId = parent.id; + } this.key = key; }; mockRelation.prototype.add = function(obj) { this.targetClassName = obj.className; }; +mockRelation.prototype.toJSON = function() { + return { + __type: 'Relation', + className: this.targetClassName + }; +}; +mockRelation.prototype._ensureParentAndKey = function(parent, key) { + this.key = this.key || key; + if (this.key !== key) { + throw new Error( + 'Internal Error. Relation retrieved from two different keys.' + ); + } + if (this.parent) { + if (this.parent.className !== parent.className) { + throw new Error( + 'Internal Error. Relation retrieved from two different Objects.' + ); + } + if (this.parent.id) { + if (this.parent.id !== parent.id) { + throw new Error( + 'Internal Error. Relation retrieved from two different Objects.' + ); + } + } else if (parent.id) { + this.parent = parent; + } + } else { + this.parent = parent; + } +}; jest.setMock('../ParseRelation', mockRelation); const mockQuery = function(className) { @@ -516,35 +551,14 @@ describe('ParseObject', () => { }); it('can be cloned with relation (#381)', () => { - var relationJSON = {__type: 'Relation', className: 'Bar'}; - var o = ParseObject.fromJSON({ + const relationJSON = {__type: 'Relation', className: 'Bar'}; + const o = ParseObject.fromJSON({ objectId: '7777777777', className: 'Foo', aRelation: relationJSON, }); - var o2 = o.clone(); - expect(o2._getSaveJSON()).toEqual({ - aRelation: relationJSON, - }); - var newRel = o2.relation('aRelation'); - var bar = ParseObject.fromJSON({ - objectId: '8888888888', - className: 'Bar', - }); - newRel.add(bar); - expect(newRel.toJSON()).toEqual(relationJSON); - expect(o2._getSaveJSON()).toEqual({ - aRelation: { - __op: 'AddRelation', - objects: [ - { - __type: 'Pointer', - className: 'Bar', - objectId: '8888888888' - }, - ], - }, - }); + const o2 = o.clone(); + expect(o2._getSaveJSON().aRelation).toEqual(relationJSON); }); it('can detect dirty object children', () => { From d2a933508d8082af74dec90d19eefc6091b85dd3 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Sat, 1 Dec 2018 17:47:45 -0600 Subject: [PATCH 6/6] more tests --- integration/test/ParseObjectTest.js | 31 +++++++++++++++++++++++------ src/ParseOp.js | 2 ++ src/__tests__/ParseOp-test.js | 15 ++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index a811dd403..edde7e290 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -1456,17 +1456,36 @@ describe('Parse Object', () => { } }); - it('can clone with relation', (done) => { - const o = Parse.Object.fromJSON({ - objectId: '7777777777', - className: 'Foo', - aRelation: { __type: 'Relation', className: 'Foo' }, - }); + it('can clone with relation', async (done) => { + const testObject = new TestObject(); + const o = new TestObject(); + await o.save(); + await testObject.save(); + let relation = o.relation('aRelation'); + relation.add(testObject); + await o.save(); + const o2 = o.clone(); assert.equal( o.relation('aRelation').targetClassName, o2.relation('aRelation').targetClassName ); + let relations = await o.relation('aRelation').query().find(); + assert.equal(relations.length, 1); + + relations = await o2.relation('aRelation').query().find(); + assert.equal(relations.length, 0); + + relation = o2.relation('aRelation'); + relation.add(testObject); + await o2.save(); + + relations = await o.relation('aRelation').query().find(); + assert.equal(relations.length, 1); + + relations = await o2.relation('aRelation').query().find(); + assert.equal(relations.length, 1); + done(); }); }); diff --git a/src/ParseOp.js b/src/ParseOp.js index 4736897dc..91f7a9c16 100644 --- a/src/ParseOp.js +++ b/src/ParseOp.js @@ -392,6 +392,8 @@ export class RelationOp extends Op { return this; } else if (previous instanceof UnsetOp) { throw new Error('You cannot modify a relation after deleting it.'); + } else if (previous instanceof SetOp && previous._value instanceof ParseRelation) { + return this; } else if (previous instanceof RelationOp) { if (previous._targetClassName && previous._targetClassName !== this._targetClassName) { diff --git a/src/__tests__/ParseOp-test.js b/src/__tests__/ParseOp-test.js index be638e341..d600dfe4a 100644 --- a/src/__tests__/ParseOp-test.js +++ b/src/__tests__/ParseOp-test.js @@ -26,6 +26,13 @@ mockObject.prototype._getId = function() { mockObject.registerSubclass = function() {}; jest.setMock('../ParseObject', mockObject); +const mockRelation = function(parent, key) { + this.parent = parent; + this.key = key; +} +jest.setMock('../ParseRelation', mockRelation); + +const ParseRelation = require('../ParseRelation'); const ParseObject = require('../ParseObject'); const ParseOp = require('../ParseOp'); const { @@ -364,4 +371,12 @@ describe('ParseOp', () => { ] }); }); + + it('can merge Relation Op with the previous Op', () => { + const r = new RelationOp(); + const relation = new ParseRelation(null, null); + const set = new SetOp(relation); + + expect(r.mergeWith(set)).toEqual(r); + }); });