From 8f1717e4b02dddd0b3733fb9a96e664b91014e90 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 02:55:54 +1100 Subject: [PATCH 01/11] decode date --- src/__tests__/ParseObject-test.js | 5 +++++ src/decode.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 892e6fb11..10e268f8a 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -255,11 +255,13 @@ describe('ParseObject', () => { }); it('can be inflated from server JSON', () => { + const date = new Date(); const json = { className: 'Item', createdAt: '2013-12-14T04:51:19Z', objectId: 'I1', size: 'medium', + date: date }; const o = ParseObject.fromJSON(json); expect(o.className).toBe('Item'); @@ -268,8 +270,10 @@ describe('ParseObject', () => { size: 'medium', createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), + date }); expect(o.dirty()).toBe(false); + expect(o.get('date')).toBeInstanceOf(Date); }); it('can override old data when inflating from the server', () => { @@ -1239,6 +1243,7 @@ describe('ParseObject', () => { expect(o.op('count')).toBe(undefined); }); + it('can revert a specific field in unsaved ops', () => { const o = ParseObject.fromJSON({ className: 'Item', diff --git a/src/decode.js b/src/decode.js index ac4cca011..42512fba1 100644 --- a/src/decode.js +++ b/src/decode.js @@ -17,7 +17,7 @@ import { opFromJSON } from './ParseOp'; import ParseRelation from './ParseRelation'; export default function decode(value: any): any { - if (value === null || typeof value !== 'object') { + if (value === null || typeof value !== 'object' || value instanceof Date) { return value; } if (Array.isArray(value)) { From 47cfe3f666a34d85f01fd91664e1f50d300c5a3e Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 02:58:42 +1100 Subject: [PATCH 02/11] Update ParseObject-test.js --- src/__tests__/ParseObject-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 10e268f8a..0507709df 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -1243,7 +1243,7 @@ describe('ParseObject', () => { expect(o.op('count')).toBe(undefined); }); - + it('can revert a specific field in unsaved ops', () => { const o = ParseObject.fromJSON({ className: 'Item', From 6e51dae0fe93e65f5a75f9bb83ee49db05b7eae6 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 03:19:57 +1100 Subject: [PATCH 03/11] Update ParseQuery-test.js --- src/__tests__/ParseQuery-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index c5d7f86fc..814140de4 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -3251,7 +3251,7 @@ describe('ParseQuery LocalDatastore', () => { updatedAt: new Date('2018-08-12T00:00:00.000Z'), }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj2, obj3]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj3, obj2]); mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); @@ -3280,7 +3280,7 @@ describe('ParseQuery LocalDatastore', () => { expect(results[2].get('number')).toEqual(2); q = new ParseQuery('Item'); - q.descending('_created_at'); + q.ascending('_created_at'); q.fromLocalDatastore(); results = await q.find(); expect(results[0].get('number')).toEqual(2); @@ -3288,7 +3288,7 @@ describe('ParseQuery LocalDatastore', () => { expect(results[2].get('number')).toEqual(4); q = new ParseQuery('Item'); - q.descending('_updated_at'); + q.ascending('_updated_at'); q.fromLocalDatastore(); results = await q.find(); expect(results[0].get('number')).toEqual(2); From 2ca897cb5b22d83977b2f131b4f6612305070439 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 03:57:21 +1100 Subject: [PATCH 04/11] Update ParseObject-test.js --- src/__tests__/ParseObject-test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 0507709df..35ae591cd 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -1243,7 +1243,6 @@ describe('ParseObject', () => { expect(o.op('count')).toBe(undefined); }); - it('can revert a specific field in unsaved ops', () => { const o = ParseObject.fromJSON({ className: 'Item', From 943750e223e005860c2f84e6bf32f7ca436a6dcd Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 12:07:13 +1100 Subject: [PATCH 05/11] Update ParseQuery-test.js --- src/__tests__/ParseQuery-test.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 814140de4..6e451bc01 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -3251,7 +3251,16 @@ describe('ParseQuery LocalDatastore', () => { updatedAt: new Date('2018-08-12T00:00:00.000Z'), }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj3, obj2]); + const obj4 = { + className: 'Item', + objectId: 'objectId3', + password: 123, + number: 4, + createdAt: new Date('2018-08-12T00:00:00.000Z'), + updatedAt: new Date('2018-08-12T00:00:00.000Z'), + }; + + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj3, obj2, obj4]); mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); @@ -3262,22 +3271,16 @@ describe('ParseQuery LocalDatastore', () => { expect(results[0].get('number')).toEqual(2); expect(results[1].get('number')).toEqual(3); expect(results[2].get('number')).toEqual(4); + expect(results[3].get('number')).toEqual(4); q = new ParseQuery('Item'); q.descending('number'); q.fromLocalDatastore(); results = await q.find(); expect(results[0].get('number')).toEqual(4); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(2); - - q = new ParseQuery('Item'); - q.descending('number'); - q.fromLocalDatastore(); - results = await q.find(); - expect(results[0].get('number')).toEqual(4); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(2); + expect(results[1].get('number')).toEqual(4); + expect(results[2].get('number')).toEqual(3); + expect(results[3].get('number')).toEqual(2); q = new ParseQuery('Item'); q.ascending('_created_at'); From 5229794857c9197fc9545ab108cc5dc62f6f2724 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 12:08:27 +1100 Subject: [PATCH 06/11] Update ParseQuery-test.js --- src/__tests__/ParseQuery-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 6e451bc01..5aea441d4 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -3253,7 +3253,7 @@ describe('ParseQuery LocalDatastore', () => { const obj4 = { className: 'Item', - objectId: 'objectId3', + objectId: 'objectId4', password: 123, number: 4, createdAt: new Date('2018-08-12T00:00:00.000Z'), From d871f0422c509cea74f670ecff0ff82cbf6c2fab Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 14:12:04 +1100 Subject: [PATCH 07/11] add dirty parameter to fromJSON --- src/ParseObject.js | 5 +++- src/__tests__/ParseObject-test.js | 44 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/ParseObject.js b/src/ParseObject.js index 1efb3101c..28b2ee7d8 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -1752,10 +1752,11 @@ class ParseObject { * @param {object} json The JSON map of the Object's data * @param {boolean} override In single instance mode, all old server data * is overwritten if this is set to true + * @param {boolean} dirty Whether the Parse.Object should set JSON keys to dirty * @static * @returns {Parse.Object} A Parse.Object reference */ - static fromJSON(json: any, override?: boolean) { + static fromJSON(json: any, override?: boolean, dirty?: boolean) { if (!json.className) { throw new Error('Cannot create an object without a className'); } @@ -1765,6 +1766,8 @@ class ParseObject { for (const attr in json) { if (attr !== 'className' && attr !== '__type') { otherAttributes[attr] = json[attr]; + o.set(attr, json[attr]) + } } } if (override) { diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 35ae591cd..a8a1db0a3 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -276,6 +276,50 @@ describe('ParseObject', () => { expect(o.get('date')).toBeInstanceOf(Date); }); + it('can be inflated from server JSON', () => { + const date = new Date(); + const json = { + className: 'Item', + createdAt: '2013-12-14T04:51:19Z', + objectId: 'I1', + size: 'medium', + date: date + }; + const o = ParseObject.fromJSON(json); + expect(o.className).toBe('Item'); + expect(o.id).toBe('I1'); + expect(o.attributes).toEqual({ + size: 'medium', + createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), + updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), + date + }); + expect(o.dirty()).toBe(false); + expect(o.get('date')).toBeInstanceOf(Date); + }); + + it('can be dirty with fromJSON', () => { + const date = new Date(); + const json = { + className: 'Item', + createdAt: '2013-12-14T04:51:19Z', + objectId: 'I1', + size: 'medium', + date: date + }; + const o = ParseObject.fromJSON(json, false, true); + expect(o.className).toBe('Item'); + expect(o.id).toBe('I1'); + expect(o.attributes).toEqual({ + size: 'medium', + createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), + updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), + date + }); + expect(o.dirty()).toBe(true); + expect(o.dirtyKeys()).toEqual([ 'size', 'date' ]); + }); + it('can override old data when inflating from the server', () => { const o = ParseObject.fromJSON({ className: 'Item', From 72d32972e2e353f444ad41bc4031a40bb908c99b Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 14:12:11 +1100 Subject: [PATCH 08/11] Update ParseObject.js --- src/ParseObject.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ParseObject.js b/src/ParseObject.js index 28b2ee7d8..97984e71e 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -1766,6 +1766,7 @@ class ParseObject { for (const attr in json) { if (attr !== 'className' && attr !== '__type') { otherAttributes[attr] = json[attr]; + if (dirty) { o.set(attr, json[attr]) } } From 5cc10f4b032a232887d08046908547a910204c93 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 14:17:49 +1100 Subject: [PATCH 09/11] Update ParseObject-test.js --- src/__tests__/ParseObject-test.js | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index a8a1db0a3..935bb1c8a 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -276,28 +276,6 @@ describe('ParseObject', () => { expect(o.get('date')).toBeInstanceOf(Date); }); - it('can be inflated from server JSON', () => { - const date = new Date(); - const json = { - className: 'Item', - createdAt: '2013-12-14T04:51:19Z', - objectId: 'I1', - size: 'medium', - date: date - }; - const o = ParseObject.fromJSON(json); - expect(o.className).toBe('Item'); - expect(o.id).toBe('I1'); - expect(o.attributes).toEqual({ - size: 'medium', - createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), - updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), - date - }); - expect(o.dirty()).toBe(false); - expect(o.get('date')).toBeInstanceOf(Date); - }); - it('can be dirty with fromJSON', () => { const date = new Date(); const json = { From f51b8fbfcab0d6f2ade58705f74ad8102b3cba38 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 14:56:36 +1100 Subject: [PATCH 10/11] integration + run prettier --- integration/test/ParseObjectTest.js | 28 ++++++++++++++++++++++++++++ src/ParseObject.js | 2 +- src/__tests__/ParseObject-test.js | 10 +++++----- src/__tests__/ParseQuery-test.js | 7 ++++++- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index 65d932258..06d9ad75b 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -2012,4 +2012,32 @@ describe('Parse Object', () => { const fetched = await query.get(user.id); assert.equal(fetched.isDataAvailable(), true); }); + it('from json save data', async () => { + const json = { + className: 'TestObject', + date: new Date(), + array: [], + object: {}, + string: '', + }; + const obj = Parse.Object.fromJSON(json, false, true); + expect(obj.get('date')).toBeDefined(); + expect(obj.get('date')).toBeInstanceOf(Date); + expect(obj.get('array')).toBeDefined(); + expect(obj.get('array')).toBeInstanceOf(Array); + expect(obj.get('object')).toBeDefined(); + expect(obj.get('object')).toBeInstanceOf(Object); + expect(obj.get('string')).toBeDefined(); + expect(obj.get('string')).toBeInstanceOf(String); + await obj.save(); + await obj.fetch(); + expect(obj.get('date')).toBeDefined(); + expect(obj.get('date')).toBeInstanceOf(Date); + expect(obj.get('array')).toBeDefined(); + expect(obj.get('array')).toBeInstanceOf(Array); + expect(obj.get('object')).toBeDefined(); + expect(obj.get('object')).toBeInstanceOf(Object); + expect(obj.get('string')).toBeDefined(); + expect(obj.get('string')).toBeInstanceOf(String); + }); }); diff --git a/src/ParseObject.js b/src/ParseObject.js index 1f92872af..6ca88dba8 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -1838,7 +1838,7 @@ class ParseObject { if (attr !== 'className' && attr !== '__type') { otherAttributes[attr] = json[attr]; if (dirty) { - o.set(attr, json[attr]) + o.set(attr, json[attr]); } } } diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 2e3e00da2..2dbdf3535 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -262,7 +262,7 @@ describe('ParseObject', () => { createdAt: '2013-12-14T04:51:19Z', objectId: 'I1', size: 'medium', - date: date + date: date, }; const o = ParseObject.fromJSON(json); expect(o.className).toBe('Item'); @@ -271,7 +271,7 @@ describe('ParseObject', () => { size: 'medium', createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), - date + date, }); expect(o.dirty()).toBe(false); expect(o.get('date')).toBeInstanceOf(Date); @@ -284,7 +284,7 @@ describe('ParseObject', () => { createdAt: '2013-12-14T04:51:19Z', objectId: 'I1', size: 'medium', - date: date + date: date, }; const o = ParseObject.fromJSON(json, false, true); expect(o.className).toBe('Item'); @@ -293,10 +293,10 @@ describe('ParseObject', () => { size: 'medium', createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), - date + date, }); expect(o.dirty()).toBe(true); - expect(o.dirtyKeys()).toEqual([ 'size', 'date' ]); + expect(o.dirtyKeys()).toEqual(['size', 'date']); }); it('can override old data when inflating from the server', () => { diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 5aea441d4..1937b113f 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -3260,7 +3260,12 @@ describe('ParseQuery LocalDatastore', () => { updatedAt: new Date('2018-08-12T00:00:00.000Z'), }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj3, obj2, obj4]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [ + obj1, + obj3, + obj2, + obj4, + ]); mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); From 3f6c45603e49fa9fdb1db26d5609c6d2e9d5f0e8 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 11 Feb 2021 14:57:31 +1100 Subject: [PATCH 11/11] Update ParseObjectTest.js --- integration/test/ParseObjectTest.js | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index 06d9ad75b..3c94ad360 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -2012,6 +2012,7 @@ describe('Parse Object', () => { const fetched = await query.get(user.id); assert.equal(fetched.isDataAvailable(), true); }); + it('from json save data', async () => { const json = { className: 'TestObject',