Skip to content

Commit 2b1fc0a

Browse files
yuki-takeichidplewis
authored andcommitted
Support clone with relation (fix #381) (#382)
* fix broken test * Support clone with relation (fix #381) * fix bug * fix bug * test fix * more tests
1 parent cea20a6 commit 2b1fc0a

File tree

5 files changed

+103
-2
lines changed

5 files changed

+103
-2
lines changed

integration/test/ParseObjectTest.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,4 +1455,37 @@ describe('Parse Object', () => {
14551455
done();
14561456
}
14571457
});
1458+
1459+
it('can clone with relation', async (done) => {
1460+
const testObject = new TestObject();
1461+
const o = new TestObject();
1462+
await o.save();
1463+
await testObject.save();
1464+
let relation = o.relation('aRelation');
1465+
relation.add(testObject);
1466+
await o.save();
1467+
1468+
const o2 = o.clone();
1469+
assert.equal(
1470+
o.relation('aRelation').targetClassName,
1471+
o2.relation('aRelation').targetClassName
1472+
);
1473+
let relations = await o.relation('aRelation').query().find();
1474+
assert.equal(relations.length, 1);
1475+
1476+
relations = await o2.relation('aRelation').query().find();
1477+
assert.equal(relations.length, 0);
1478+
1479+
relation = o2.relation('aRelation');
1480+
relation.add(testObject);
1481+
await o2.save();
1482+
1483+
relations = await o.relation('aRelation').query().find();
1484+
assert.equal(relations.length, 1);
1485+
1486+
relations = await o2.relation('aRelation').query().find();
1487+
assert.equal(relations.length, 1);
1488+
1489+
done();
1490+
});
14581491
});

src/ParseObject.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,10 @@ class ParseObject {
652652
!(changes[k] instanceof ParseACL)
653653
) {
654654
newOps[k] = new SetOp(new ParseACL(changes[k]));
655+
} else if (changes[k] instanceof ParseRelation) {
656+
var relation = new ParseRelation(this, k);
657+
relation.targetClassName = changes[k].targetClassName;
658+
newOps[k] = new SetOp(relation);
655659
} else {
656660
newOps[k] = new SetOp(changes[k]);
657661
}

src/ParseOp.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ export class RelationOp extends Op {
392392
return this;
393393
} else if (previous instanceof UnsetOp) {
394394
throw new Error('You cannot modify a relation after deleting it.');
395+
} else if (previous instanceof SetOp && previous._value instanceof ParseRelation) {
396+
return this;
395397
} else if (previous instanceof RelationOp) {
396398
if (previous._targetClassName &&
397399
previous._targetClassName !== this._targetClassName) {

src/__tests__/ParseObject-test.js

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jest.dontMock('../ParseFile');
2222
jest.dontMock('../ParseGeoPoint');
2323
jest.dontMock('../ParseObject');
2424
jest.dontMock('../ParseOp');
25+
jest.dontMock('../ParseRelation');
2526
jest.dontMock('../RESTController');
2627
jest.dontMock('../SingleInstanceStateController');
2728
jest.dontMock('../TaskQueue');
@@ -35,13 +36,48 @@ jest.dontMock('./test_helpers/mockXHR');
3536
jest.useFakeTimers();
3637

3738
const mockRelation = function(parent, key) {
38-
this.parentClass = parent.className;
39-
this.parentId = parent.id;
39+
// The parent and key fields will be populated by the parent
40+
if (parent) {
41+
this.parentClass = parent.className;
42+
this.parentId = parent.id;
43+
}
4044
this.key = key;
4145
};
4246
mockRelation.prototype.add = function(obj) {
4347
this.targetClassName = obj.className;
4448
};
49+
mockRelation.prototype.toJSON = function() {
50+
return {
51+
__type: 'Relation',
52+
className: this.targetClassName
53+
};
54+
};
55+
mockRelation.prototype._ensureParentAndKey = function(parent, key) {
56+
this.key = this.key || key;
57+
if (this.key !== key) {
58+
throw new Error(
59+
'Internal Error. Relation retrieved from two different keys.'
60+
);
61+
}
62+
if (this.parent) {
63+
if (this.parent.className !== parent.className) {
64+
throw new Error(
65+
'Internal Error. Relation retrieved from two different Objects.'
66+
);
67+
}
68+
if (this.parent.id) {
69+
if (this.parent.id !== parent.id) {
70+
throw new Error(
71+
'Internal Error. Relation retrieved from two different Objects.'
72+
);
73+
}
74+
} else if (parent.id) {
75+
this.parent = parent;
76+
}
77+
} else {
78+
this.parent = parent;
79+
}
80+
};
4581
jest.setMock('../ParseRelation', mockRelation);
4682

4783
const mockQuery = function(className) {
@@ -514,6 +550,17 @@ describe('ParseObject', () => {
514550
expect(rel.targetClassName).toBe('Person');
515551
});
516552

553+
it('can be cloned with relation (#381)', () => {
554+
const relationJSON = {__type: 'Relation', className: 'Bar'};
555+
const o = ParseObject.fromJSON({
556+
objectId: '7777777777',
557+
className: 'Foo',
558+
aRelation: relationJSON,
559+
});
560+
const o2 = o.clone();
561+
expect(o2._getSaveJSON().aRelation).toEqual(relationJSON);
562+
});
563+
517564
it('can detect dirty object children', () => {
518565
const o = new ParseObject('Person');
519566
o._finishFetch({

src/__tests__/ParseOp-test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ mockObject.prototype._getId = function() {
2626
mockObject.registerSubclass = function() {};
2727
jest.setMock('../ParseObject', mockObject);
2828

29+
const mockRelation = function(parent, key) {
30+
this.parent = parent;
31+
this.key = key;
32+
}
33+
jest.setMock('../ParseRelation', mockRelation);
34+
35+
const ParseRelation = require('../ParseRelation');
2936
const ParseObject = require('../ParseObject');
3037
const ParseOp = require('../ParseOp');
3138
const {
@@ -364,4 +371,12 @@ describe('ParseOp', () => {
364371
]
365372
});
366373
});
374+
375+
it('can merge Relation Op with the previous Op', () => {
376+
const r = new RelationOp();
377+
const relation = new ParseRelation(null, null);
378+
const set = new SetOp(relation);
379+
380+
expect(r.mergeWith(set)).toEqual(r);
381+
});
367382
});

0 commit comments

Comments
 (0)