diff --git a/src/ObjectStateMutations.js b/src/ObjectStateMutations.js index 271e4f6b5..114842ac8 100644 --- a/src/ObjectStateMutations.js +++ b/src/ObjectStateMutations.js @@ -122,7 +122,8 @@ export function estimateAttributes( const fields = attr.split('.'); const first = fields[0]; const last = fields[fields.length - 1]; - data[first] = { ...serverData[first] }; + // data could be locally set/updated and not saved yet, or multiple ops a.b and a.c can have been processed already + data[first] = { ...(data[first] || serverData[first]) }; let object = { ...data }; for (let i = 0; i < fields.length - 1; i++) { const key = fields[i]; diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 06a7f3c2f..d01603bb1 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -500,6 +500,52 @@ describe('ParseObject', () => { expect(o.has('age')).toBe(true); }); + it('setting multiple properties in an object', () => { + const o = new ParseObject('Person'); + o._finishFetch({ + objectId: 'p98', + age: 28, + data: { foo: 'bar' }, + }); + expect(o.dirty()).toBe(false); + expect(o.has('data')).toBe(true); + + o.set('data.score', 10); + expect(o.get('data')).toEqual({ foo: 'bar', score: 10 }); + expect(o.dirty('data')).toBe(true); + + o.set('data.score2', 12); + expect(o.get('data')).toEqual({ foo: 'bar', score: 10, score2: 12 }); + expect(o.dirty('data')).toBe(true); + }); + + it('can set multiple nested fields (regression test for #1450)', () => { + const o = new ParseObject('Person'); + o._finishFetch({ + objectId: 'setNested2_1450', + objectField: { + number: 5, + letter: 'a', + }, + }); + + expect(o.attributes).toEqual({ + objectField: { number: 5, letter: 'a' }, + }); + o.set('objectField.number', 20); + o.set('objectField.letter', 'b'); + + expect(o.attributes).toEqual({ + objectField: { number: 20, letter: 'b' }, + }); + expect(o.op('objectField.number') instanceof SetOp).toBe(true); + expect(o.dirtyKeys()).toEqual(['objectField.number', 'objectField.letter', 'objectField']); + expect(o._getSaveJSON()).toEqual({ + 'objectField.number': 20, + 'objectField.letter': 'b', + }); + }); + it('can tell if a field is dirty', () => { const o = new ParseObject('Person'); o._finishFetch({