Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions integration/test/ParseObjectTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,27 @@ describe('Parse Object', () => {
assert.equal(result.get('objectField').number, 20);
});

it('can increment nested field and retain full object', async () => {
const obj = new TestObject();
obj.set('objectField', { number: 5, letter: 'a' });
assert.equal(obj.get('objectField').number, 5);
assert.equal(obj.get('objectField').letter, 'a');
await obj.save();

obj.increment('objectField.number', 15);
assert.equal(obj.get('objectField').number, 20);
assert.equal(obj.get('objectField').letter, 'a');
await obj.save();

assert.equal(obj.get('objectField').number, 20);
assert.equal(obj.get('objectField').letter, 'a');

const query = new Parse.Query(TestObject);
const result = await query.get(obj.id);
assert.equal(result.get('objectField').number, 20);
assert.equal(result.get('objectField').letter, 'a');
});

it('can increment non existing field', async () => {
const obj = new TestObject();
obj.set('objectField', { number: 5 });
Expand Down
10 changes: 8 additions & 2 deletions src/ParseObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ class ParseObject {
for (attr in pending) {
if (pending[attr] instanceof RelationOp) {
changes[attr] = pending[attr].applyTo(undefined, this, attr);
} else if (!(attr in response)) {
} else if (!(attr in response) && !attr.includes('.')) {
// Only SetOps and UnsetOps should not come back with results
changes[attr] = pending[attr].applyTo(undefined);
}
Expand All @@ -407,7 +407,13 @@ class ParseObject {
} else if (attr === 'ACL') {
changes[attr] = new ParseACL(response[attr]);
} else if (attr !== 'objectId') {
changes[attr] = decode(response[attr]);
const val = decode(response[attr]);
if (val && Object.getPrototypeOf(val) === Object.prototype) {
// Update the object by merging in updates w/ old object
changes[attr] = { ...this.attributes[attr], ...val }
} else {
changes[attr] = val
}
if (changes[attr] instanceof UnsetOp) {
changes[attr] = undefined;
}
Expand Down
8 changes: 5 additions & 3 deletions src/__tests__/ObjectStateMutations-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,19 @@ describe('ObjectStateMutations', () => {
});

it('can estimate attributes for nested documents', () => {
const serverData = { objectField: { counter: 10 } };
const serverData = { objectField: { counter: 10, letter: 'a' } };
let pendingOps = [{ 'objectField.counter': new ParseOps.IncrementOp(2) }];
expect(ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId')).toEqual({
objectField: {
counter: 12
counter: 12,
letter: 'a'
},
});
pendingOps = [{ 'objectField.counter': new ParseOps.SetOp(20) }];
expect(ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId')).toEqual({
objectField: {
counter: 20
counter: 20,
letter: 'a'
},
});
});
Expand Down
45 changes: 42 additions & 3 deletions src/__tests__/ParseObject-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,20 +610,21 @@ describe('ParseObject', () => {
o._finishFetch({
objectId: 'setNested',
objectField: {
number: 5
number: 5,
letter: 'a'
},
otherField: {},
});

expect(o.attributes).toEqual({
objectField: { number: 5 },
objectField: { number: 5, letter: 'a' },
otherField: {},
});
o.set('otherField', { hello: 'world' });
o.set('objectField.number', 20);

expect(o.attributes).toEqual({
objectField: { number: 20 },
objectField: { number: 20, letter: 'a' },
otherField: { hello: 'world' },
});
expect(o.op('objectField.number') instanceof SetOp).toBe(true);
Expand All @@ -634,6 +635,44 @@ describe('ParseObject', () => {
});
});

it('can increment a nested field', () => {
const o = new ParseObject('Person');
o._finishFetch({
objectId: 'incNested',
objectField: {
number: 5,
letter: 'a'
},
});

expect(o.attributes).toEqual({
objectField: { number: 5, letter: 'a' },
});
o.increment('objectField.number');

expect(o.attributes).toEqual({
objectField: { number: 6, letter: 'a' },
});
expect(o.op('objectField.number') instanceof IncrementOp).toBe(true);
expect(o.dirtyKeys()).toEqual(['objectField.number', 'objectField']);
expect(o._getSaveJSON()).toEqual({
'objectField.number': {
"__op": "Increment",
"amount": 1
},
});

// Nested objects only return values changed
o._handleSaveResponse({
objectId: 'incNested',
objectField: {
number: 6
}
})
expect(o.get('objectField').number).toEqual(6)
expect(o.get('objectField').letter).toEqual('a')
});

it('ignore set nested field on new object', () => {
const o = new ParseObject('Person');
o.set('objectField.number', 20);
Expand Down