Skip to content

Commit

Permalink
fix: Internal Referencing for Increment Dot Notation (#1255)
Browse files Browse the repository at this point in the history
* test

* lint

* Cleanup

* Revert package-lock.json
  • Loading branch information
dplewis authored Nov 12, 2020
1 parent f443834 commit 49df2f5
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 8 deletions.
12 changes: 9 additions & 3 deletions integration/test/ParseObjectTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,24 +256,30 @@ describe('Parse Object', () => {
});

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

obj.increment('objectField.number', 15);
assert.deepStrictEqual(obj.attributes.objectField, { number: 20, letter: 'a' });
assert.deepStrictEqual(obj.attributes.objectField, { number: 20, letter: 'a' });

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');
assert.deepStrictEqual(obj.attributes.objectField, { number: 20, letter: 'a' });

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

it('can increment non existing field', async () => {
Expand Down Expand Up @@ -321,7 +327,7 @@ describe('Parse Object', () => {
await obj.save();
assert.equal(false, true);
} catch(error) {
assert.equal(error.message, "Cannot create property 'dot' on string 'world'");
assert.equal(error.message, 'schema mismatch for TestObject.hello; expected String but got Object');
}
});

Expand Down
2 changes: 1 addition & 1 deletion integration/test/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ beforeAll((done) => {
const { app } = require('../server');
const httpServer = require('http').createServer(app);

httpServer.listen(1337, () => {
httpServer.on('error', console.log).listen(1337, () => {
console.log('parse-server running on port 1337.');
done();
});
Expand Down
4 changes: 3 additions & 1 deletion src/ObjectStateMutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ export function estimateAttributes(serverData: AttributeMap, pendingOps: Array<O
if (attr.includes('.')) {
// convert a.b.c into { a: { b: { c: value } } }
const fields = attr.split('.');
const first = fields[0];
const last = fields[fields.length - 1];
let object = Object.assign({}, data);
data[first] = { ...serverData[first] };
let object = { ...data };
for (let i = 0; i < fields.length - 1; i++) {
object = object[fields[i]];
}
Expand Down
5 changes: 2 additions & 3 deletions src/ParseObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,9 @@ class ParseObject {
} else if (attr !== 'objectId') {
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 }
changes[attr] = { ...this.attributes[attr], ...val };
} else {
changes[attr] = val
changes[attr] = val;
}
if (changes[attr] instanceof UnsetOp) {
changes[attr] = undefined;
Expand Down
36 changes: 36 additions & 0 deletions src/__tests__/ParseObject-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jest.dontMock('../ParseFile');
jest.dontMock('../ParseGeoPoint');
jest.dontMock('../ParseObject');
jest.dontMock('../ParseOp');
jest.dontMock('../ParsePolygon');
jest.dontMock('../ParseRelation');
jest.dontMock('../RESTController');
jest.dontMock('../SingleInstanceStateController');
Expand Down Expand Up @@ -147,6 +148,7 @@ const ParseACL = require('../ParseACL').default;
const ParseError = require('../ParseError').default;
const ParseFile = require('../ParseFile').default;
const ParseGeoPoint = require('../ParseGeoPoint').default;
const ParsePolygon = require('../ParsePolygon').default;
const ParseObject = require('../ParseObject').default;
const ParseOp = require('../ParseOp');
const RESTController = require('../RESTController');
Expand Down Expand Up @@ -1104,6 +1106,40 @@ describe('ParseObject', () => {
expect(p.op('age')).toBe(undefined);
});

it('handle GeoPoint changes for server', () => {
const p = new ParseObject('Person');
p.id = 'PPoint';
const created = new Date();
const geopoint = new ParseGeoPoint(0, 0);
p._handleSaveResponse({
createdAt: created.toISOString(),
point: geopoint.toJSON(),
});
expect(p._getServerData()).toEqual({
updatedAt: created,
createdAt: created,
point: geopoint,
});
expect(p._getServerData().point instanceof ParseGeoPoint).toBe(true);
});

it('handle Polygon changes for server', () => {
const p = new ParseObject('Person');
p.id = 'PPolygon';
const created = new Date();
const polygon = new ParsePolygon([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]);
p._handleSaveResponse({
createdAt: created.toISOString(),
shape: polygon.toJSON(),
});
expect(p._getServerData()).toEqual({
updatedAt: created,
createdAt: created,
shape: polygon,
});
expect(p._getServerData().shape instanceof ParsePolygon).toBe(true);
});

it('handle createdAt string for server', () => {
const p = new ParseObject('Person');
p.id = 'P9';
Expand Down

0 comments on commit 49df2f5

Please sign in to comment.