From 293011e0b537849b13d7488543f96c7c79f9b44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kartal=20Kaan=20Bozdo=C4=9Fan?= Date: Thu, 13 May 2021 19:31:47 +0300 Subject: [PATCH 1/5] Better support for nested keys --- src/ObjectStateMutations.js | 14 ++++++++++++-- src/ParseObject.js | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ObjectStateMutations.js b/src/ObjectStateMutations.js index bcac048a0..2ee60160d 100644 --- a/src/ObjectStateMutations.js +++ b/src/ObjectStateMutations.js @@ -154,6 +154,16 @@ export function estimateAttributes( return data; } +function nestedSet(obj, key, value) { + const path = key.split('.'); + for (let i = 0; i < path.length - 1; i++) { + if (!(path[i] in obj)) obj[path[i]] = {}; + obj = obj[path[i]]; + } + if (typeof value === 'undefined') delete obj[path[path.length - 1]]; + else obj[path[path.length - 1]] = value; +} + export function commitServerChanges( serverData: AttributeMap, objectCache: ObjectCache, @@ -161,7 +171,7 @@ export function commitServerChanges( ) { for (const attr in changes) { const val = changes[attr]; - serverData[attr] = val; + nestedSet(serverData, attr, val); if ( val && typeof val === 'object' && @@ -170,7 +180,7 @@ export function commitServerChanges( !(val instanceof ParseRelation) ) { const json = encode(val, false, true); - objectCache[attr] = JSON.stringify(json); + nestedSet(objectCache, attr, JSON.stringify(json)); } } } diff --git a/src/ParseObject.js b/src/ParseObject.js index 8f4198cfd..87738d56f 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -409,7 +409,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) && !attr.includes('.')) { + } else if (!(attr in response)) { // Only SetOps and UnsetOps should not come back with results changes[attr] = pending[attr].applyTo(undefined); } From 7b8a66a2b17977ec2a44e82d633260764c58c984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kartal=20Kaan=20Bozdo=C4=9Fan?= Date: Thu, 13 May 2021 21:09:36 +0300 Subject: [PATCH 2/5] Added a test for nested fields Bugfix on ObjectStateMutations patch --- src/ObjectStateMutations.js | 2 +- src/__tests__/ParseObject-test.js | 39 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/ObjectStateMutations.js b/src/ObjectStateMutations.js index 2ee60160d..2d53f72a6 100644 --- a/src/ObjectStateMutations.js +++ b/src/ObjectStateMutations.js @@ -180,7 +180,7 @@ export function commitServerChanges( !(val instanceof ParseRelation) ) { const json = encode(val, false, true); - nestedSet(objectCache, attr, JSON.stringify(json)); + objectCache[attr] = JSON.stringify(json); } } } diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index e8294aef0..270ee318c 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -465,6 +465,45 @@ describe('ParseObject', () => { expect(o.attributes).toEqual({ name: 'William', behavior: 'formal' }); }); + it('can set nested fields', async () => { + // Mock XHR + CoreManager.getRESTController()._setXHR( + mockXHR([ + { + status: 200, + response: { objectId: 'yolo' }, + }, + ]) + ); + const o = new ParseObject('Person'); + expect(o.attributes).toEqual({}); + o.set('data', {}); + await o.save(); + expect(o.get('data')).toEqual({}); + o.set('data.a', {}); + CoreManager.getRESTController()._setXHR( + mockXHR([ + { + status: 200, + response: {}, + }, + ]) + ); + await o.save(); + expect(o.get('data')).toEqual({ a: {} }); + o.set('data.a.b', {}); + CoreManager.getRESTController()._setXHR( + mockXHR([ + { + status: 200, + response: {}, + }, + ]) + ); + await o.save(); + expect(o.get('data')).toEqual({ a: { b: {} } }); + }); + it('can set id with the objectId attribute', () => { const o = new ParseObject('Person'); expect(o.attributes).toEqual({}); From a628b690efd3fcd66c588ea0e9d4afcfa0ec8456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kartal=20Kaan=20Bozdo=C4=9Fan?= Date: Thu, 13 May 2021 21:30:47 +0300 Subject: [PATCH 3/5] Move the new test under integration/ --- integration/test/ParseObjectTest.js | 14 +++++++++++ src/__tests__/ParseObject-test.js | 39 ----------------------------- 2 files changed, 14 insertions(+), 39 deletions(-) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index b5c738a75..64e4a42e0 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -401,6 +401,20 @@ describe('Parse Object', () => { assert.equal(result.get('objectField').number, 20); }); + it('can set non existing nested fields to objects', async () => { + const o = new Parse.Object('Person'); + expect(o.attributes).toEqual({}); + o.set('data', {}); + await o.save(); + expect(o.get('data')).toEqual({}); + o.set('data.a', {}); + await o.save(); + expect(o.get('data')).toEqual({ a: {} }); + o.set('data.a.b', {}); + await o.save(); + expect(o.get('data')).toEqual({ a: { b: {} } }); + }); + it('can set non existing fields', async () => { const obj = new TestObject(); obj.set('objectField', { number: 5 }); diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 270ee318c..e8294aef0 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -465,45 +465,6 @@ describe('ParseObject', () => { expect(o.attributes).toEqual({ name: 'William', behavior: 'formal' }); }); - it('can set nested fields', async () => { - // Mock XHR - CoreManager.getRESTController()._setXHR( - mockXHR([ - { - status: 200, - response: { objectId: 'yolo' }, - }, - ]) - ); - const o = new ParseObject('Person'); - expect(o.attributes).toEqual({}); - o.set('data', {}); - await o.save(); - expect(o.get('data')).toEqual({}); - o.set('data.a', {}); - CoreManager.getRESTController()._setXHR( - mockXHR([ - { - status: 200, - response: {}, - }, - ]) - ); - await o.save(); - expect(o.get('data')).toEqual({ a: {} }); - o.set('data.a.b', {}); - CoreManager.getRESTController()._setXHR( - mockXHR([ - { - status: 200, - response: {}, - }, - ]) - ); - await o.save(); - expect(o.get('data')).toEqual({ a: { b: {} } }); - }); - it('can set id with the objectId attribute', () => { const o = new ParseObject('Person'); expect(o.attributes).toEqual({}); From 1ed03b3dca8af9c648606f95a6cb473b36b33a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kartal=20Kaan=20Bozdo=C4=9Fan?= Date: Thu, 13 May 2021 21:47:22 +0300 Subject: [PATCH 4/5] Modified an existing test ParseUser.get('password') used to return undefined, now password is not an attribute --- integration/test/ParseUserTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/test/ParseUserTest.js b/integration/test/ParseUserTest.js index 721104b6b..89af62a36 100644 --- a/integration/test/ParseUserTest.js +++ b/integration/test/ParseUserTest.js @@ -505,7 +505,7 @@ describe('Parse User', () => { return user.save(); }) .then(() => { - assert.equal(Object.keys(user.attributes).length, 6); + assert.equal(Object.keys(user.attributes).length, 5); assert(user.attributes.hasOwnProperty('username')); assert(user.attributes.hasOwnProperty('email')); return user.destroy(); From 6f9b11e57515cc0f6023ae621d74c78b38352961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kartal=20Kaan=20Bozdo=C4=9Fan?= Date: Fri, 14 May 2021 13:39:27 +0300 Subject: [PATCH 5/5] Use curly braces --- src/ObjectStateMutations.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ObjectStateMutations.js b/src/ObjectStateMutations.js index 2d53f72a6..7603c6a10 100644 --- a/src/ObjectStateMutations.js +++ b/src/ObjectStateMutations.js @@ -160,8 +160,11 @@ function nestedSet(obj, key, value) { if (!(path[i] in obj)) obj[path[i]] = {}; obj = obj[path[i]]; } - if (typeof value === 'undefined') delete obj[path[path.length - 1]]; - else obj[path[path.length - 1]] = value; + if (typeof value === 'undefined') { + delete obj[path[path.length - 1]]; + } else { + obj[path[path.length - 1]] = value; + } } export function commitServerChanges(