Skip to content

Commit 04e8e3e

Browse files
Merge remote-tracking branch 'upstream/master'
2 parents 7064f1d + 02af61d commit 04e8e3e

15 files changed

+585
-165
lines changed

.github/ISSUE_TEMPLATE.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
Check out [this issue](https://github.com/ParsePlatform/parse-server/issues/1271) for an ideal bug report. The closer your issue report is to that one, the more likely we are to be able to help, and the more likely we will be to fix the issue quickly!
2+
13
For implementation related questions or technical support, please refer to the [Stack Overflow](http://stackoverflow.com/questions/tagged/parse.com) and [Server Fault](https://serverfault.com/tags/parse) communities.
24

35
Make sure these boxes are checked before submitting your issue -- thanks for reporting issues back to Parse Server!

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"commander": "^2.9.0",
2727
"deepcopy": "^0.6.1",
2828
"express": "^4.13.4",
29+
"intersect": "^1.0.1",
2930
"lru-cache": "^4.0.0",
3031
"mailgun-js": "^0.7.7",
3132
"mime": "^1.3.4",

spec/ParseACL.spec.js

+34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// This is a port of the test suite:
22
// hungry/js/test/parse_acl_test.js
3+
var rest = require('../src/rest');
4+
var Config = require('../src/Config');
5+
var config = new Config('test');
6+
var auth = require('../src/Auth');
37

48
describe('Parse.ACL', () => {
59
it("acl must be valid", (done) => {
@@ -1158,4 +1162,34 @@ describe('Parse.ACL', () => {
11581162
});
11591163
});
11601164

1165+
it('regression test #701', done => {
1166+
var anonUser = {
1167+
authData: {
1168+
anonymous: {
1169+
id: '00000000-0000-0000-0000-000000000001'
1170+
}
1171+
}
1172+
};
1173+
1174+
Parse.Cloud.afterSave(Parse.User, req => {
1175+
if (!req.object.existed()) {
1176+
var user = req.object;
1177+
var acl = new Parse.ACL(user);
1178+
user.setACL(acl);
1179+
user.save(null, {useMasterKey: true}).then(user => {
1180+
new Parse.Query('_User').get(user.objectId).then(user => {
1181+
fail('should not have fetched user without public read enabled');
1182+
done();
1183+
}, error => {
1184+
expect(error.code).toEqual(Parse.Error.OBJECT_NOT_FOUND);
1185+
Parse.Cloud._removeHook('Triggers', 'afterSave', Parse.User.className);
1186+
done();
1187+
});
1188+
});
1189+
}
1190+
});
1191+
1192+
rest.create(config, auth.nobody(config), '_User', anonUser)
1193+
})
1194+
11611195
});

spec/ParseQuery.spec.js

+184
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,153 @@ describe('Parse.Query testing', () => {
14221422
});
14231423
});
14241424

1425+
it('properly includes array', (done) => {
1426+
let objects = [];
1427+
let total = 0;
1428+
while(objects.length != 5) {
1429+
let object = new Parse.Object('AnObject');
1430+
object.set('key', objects.length);
1431+
total += objects.length;
1432+
objects.push(object);
1433+
}
1434+
Parse.Object.saveAll(objects).then(() => {
1435+
let object = new Parse.Object("AContainer");
1436+
object.set('objects', objects);
1437+
return object.save();
1438+
}).then(() => {
1439+
let query = new Parse.Query('AContainer');
1440+
query.include('objects');
1441+
return query.find()
1442+
}).then((results) => {
1443+
expect(results.length).toBe(1);
1444+
let res = results[0];
1445+
let objects = res.get('objects');
1446+
expect(objects.length).toBe(5);
1447+
objects.forEach((object) => {
1448+
total -= object.get('key');
1449+
});
1450+
expect(total).toBe(0);
1451+
done()
1452+
}, () => {
1453+
fail('should not fail');
1454+
done();
1455+
})
1456+
});
1457+
1458+
it('properly includes array of mixed objects', (done) => {
1459+
let objects = [];
1460+
let total = 0;
1461+
while(objects.length != 5) {
1462+
let object = new Parse.Object('AnObject');
1463+
object.set('key', objects.length);
1464+
total += objects.length;
1465+
objects.push(object);
1466+
}
1467+
while(objects.length != 10) {
1468+
let object = new Parse.Object('AnotherObject');
1469+
object.set('key', objects.length);
1470+
total += objects.length;
1471+
objects.push(object);
1472+
}
1473+
Parse.Object.saveAll(objects).then(() => {
1474+
let object = new Parse.Object("AContainer");
1475+
object.set('objects', objects);
1476+
return object.save();
1477+
}).then(() => {
1478+
let query = new Parse.Query('AContainer');
1479+
query.include('objects');
1480+
return query.find()
1481+
}).then((results) => {
1482+
expect(results.length).toBe(1);
1483+
let res = results[0];
1484+
let objects = res.get('objects');
1485+
expect(objects.length).toBe(10);
1486+
objects.forEach((object) => {
1487+
total -= object.get('key');
1488+
});
1489+
expect(total).toBe(0);
1490+
done()
1491+
}, (err) => {
1492+
fail('should not fail');
1493+
done();
1494+
})
1495+
});
1496+
1497+
it('properly nested array of mixed objects with bad ids', (done) => {
1498+
let objects = [];
1499+
let total = 0;
1500+
while(objects.length != 5) {
1501+
let object = new Parse.Object('AnObject');
1502+
object.set('key', objects.length);
1503+
objects.push(object);
1504+
}
1505+
while(objects.length != 10) {
1506+
let object = new Parse.Object('AnotherObject');
1507+
object.set('key', objects.length);
1508+
objects.push(object);
1509+
}
1510+
Parse.Object.saveAll(objects).then(() => {
1511+
let object = new Parse.Object("AContainer");
1512+
for (var i=0; i<objects.length; i++) {
1513+
if (i%2 == 0) {
1514+
objects[i].id = 'randomThing'
1515+
} else {
1516+
total += objects[i].get('key');
1517+
}
1518+
}
1519+
object.set('objects', objects);
1520+
return object.save();
1521+
}).then(() => {
1522+
let query = new Parse.Query('AContainer');
1523+
query.include('objects');
1524+
return query.find()
1525+
}).then((results) => {
1526+
expect(results.length).toBe(1);
1527+
let res = results[0];
1528+
let objects = res.get('objects');
1529+
expect(objects.length).toBe(5);
1530+
objects.forEach((object) => {
1531+
total -= object.get('key');
1532+
});
1533+
expect(total).toBe(0);
1534+
done()
1535+
}, (err) => {
1536+
console.error(err);
1537+
fail('should not fail');
1538+
done();
1539+
})
1540+
});
1541+
1542+
it('properly fetches nested pointers', (done) =>  {
1543+
let color = new Parse.Object('Color');
1544+
color.set('hex','#133733');
1545+
let circle = new Parse.Object('Circle');
1546+
circle.set('radius', 1337);
1547+
1548+
Parse.Object.saveAll([color, circle]).then(() => {
1549+
circle.set('color', color);
1550+
let badCircle = new Parse.Object('Circle');
1551+
badCircle.id = 'badId';
1552+
let complexFigure = new Parse.Object('ComplexFigure');
1553+
complexFigure.set('consistsOf', [circle, badCircle]);
1554+
return complexFigure.save();
1555+
}).then(() => {
1556+
let q = new Parse.Query('ComplexFigure');
1557+
q.include('consistsOf.color');
1558+
return q.find()
1559+
}).then((results) => {
1560+
expect(results.length).toBe(1);
1561+
let figure = results[0];
1562+
expect(figure.get('consistsOf').length).toBe(1);
1563+
expect(figure.get('consistsOf')[0].get('color').get('hex')).toBe('#133733');
1564+
done();
1565+
}, (err) => {
1566+
fail('should not fail');
1567+
done();
1568+
})
1569+
1570+
});
1571+
14251572
it("result object creation uses current extension", function(done) {
14261573
var ParentObject = Parse.Object.extend({ className: "ParentObject" });
14271574
// Add a foo() method to ChildObject.
@@ -2209,4 +2356,41 @@ describe('Parse.Query testing', () => {
22092356
})
22102357
})
22112358

2359+
it('query with two OR subqueries (regression test #1259)', done => {
2360+
let relatedObject = new Parse.Object('Class2');
2361+
relatedObject.save().then(relatedObject => {
2362+
let anObject = new Parse.Object('Class1');
2363+
let relation = anObject.relation('relation');
2364+
relation.add(relatedObject);
2365+
return anObject.save();
2366+
}).then(anObject => {
2367+
let q1 = anObject.relation('relation').query();
2368+
q1.doesNotExist('nonExistantKey1');
2369+
let q2 = anObject.relation('relation').query();
2370+
q2.doesNotExist('nonExistantKey2');
2371+
let orQuery = Parse.Query.or(q1, q2).find().then(results => {
2372+
expect(results.length).toEqual(1);
2373+
expect(results[0].objectId).toEqual(q1.objectId);
2374+
done();
2375+
});
2376+
});
2377+
});
2378+
2379+
it('objectId containedIn with multiple large array', done => {
2380+
let obj = new Parse.Object('MyClass');
2381+
obj.save().then(obj => {
2382+
let longListOfStrings = [];
2383+
for (let i = 0; i < 130; i++) {
2384+
longListOfStrings.push(i.toString());
2385+
}
2386+
longListOfStrings.push(obj.id);
2387+
let q = new Parse.Query('MyClass');
2388+
q.containedIn('objectId', longListOfStrings);
2389+
q.containedIn('objectId', longListOfStrings);
2390+
return q.find();
2391+
}).then(results => {
2392+
expect(results.length).toEqual(1);
2393+
done();
2394+
});
2395+
});
22122396
});

spec/ParseRelation.spec.js

+64-33
Original file line numberDiff line numberDiff line change
@@ -248,46 +248,50 @@ describe('Parse.Relation testing', () => {
248248
});
249249
});
250250

251-
it("queries on relation fields with multiple ins", (done) => {
252-
var ChildObject = Parse.Object.extend("ChildObject");
253-
var childObjects = [];
254-
for (var i = 0; i < 10; i++) {
251+
it("queries on relation fields with multiple containedIn (regression test for #1271)", (done) => {
252+
let ChildObject = Parse.Object.extend("ChildObject");
253+
let childObjects = [];
254+
for (let i = 0; i < 10; i++) {
255255
childObjects.push(new ChildObject({x: i}));
256256
}
257257

258258
Parse.Object.saveAll(childObjects).then(() => {
259-
var ParentObject = Parse.Object.extend("ParentObject");
260-
var parent = new ParentObject();
259+
let ParentObject = Parse.Object.extend("ParentObject");
260+
let parent = new ParentObject();
261261
parent.set("x", 4);
262-
var relation = parent.relation("child");
263-
relation.add(childObjects[0]);
264-
relation.add(childObjects[1]);
265-
relation.add(childObjects[2]);
266-
var parent2 = new ParentObject();
262+
let parent1Children = parent.relation("child");
263+
parent1Children.add(childObjects[0]);
264+
parent1Children.add(childObjects[1]);
265+
parent1Children.add(childObjects[2]);
266+
let parent2 = new ParentObject();
267267
parent2.set("x", 3);
268-
var relation2 = parent2.relation("child");
269-
relation2.add(childObjects[4]);
270-
relation2.add(childObjects[5]);
271-
relation2.add(childObjects[6]);
272-
273-
var otherChild2 = parent2.relation("otherChild");
274-
otherChild2.add(childObjects[0]);
275-
otherChild2.add(childObjects[1]);
276-
otherChild2.add(childObjects[2]);
277-
278-
var parents = [];
279-
parents.push(parent);
280-
parents.push(parent2);
281-
return Parse.Object.saveAll(parents);
268+
let parent2Children = parent2.relation("child");
269+
parent2Children.add(childObjects[4]);
270+
parent2Children.add(childObjects[5]);
271+
parent2Children.add(childObjects[6]);
272+
273+
let parent2OtherChildren = parent2.relation("otherChild");
274+
parent2OtherChildren.add(childObjects[0]);
275+
parent2OtherChildren.add(childObjects[1]);
276+
parent2OtherChildren.add(childObjects[2]);
277+
278+
return Parse.Object.saveAll([parent, parent2]);
282279
}).then(() => {
283-
var query = new Parse.Query(ParentObject);
284-
var objects = [];
285-
objects.push(childObjects[0]);
286-
query.containedIn("child", objects);
287-
query.containedIn("otherChild", [childObjects[0]]);
288-
return query.find();
289-
}).then((list) => {
290-
equal(list.length, 2, "There should be 2 results");
280+
let objectsWithChild0InBothChildren = new Parse.Query(ParentObject);
281+
objectsWithChild0InBothChildren.containedIn("child", [childObjects[0]]);
282+
objectsWithChild0InBothChildren.containedIn("otherChild", [childObjects[0]]);
283+
return objectsWithChild0InBothChildren.find();
284+
}).then(objectsWithChild0InBothChildren => {
285+
//No parent has child 0 in both it's "child" and "otherChild" field;
286+
expect(objectsWithChild0InBothChildren.length).toEqual(0);
287+
}).then(() => {
288+
let objectsWithChild4andOtherChild1 = new Parse.Query(ParentObject);
289+
objectsWithChild4andOtherChild1.containedIn("child", [childObjects[4]]);
290+
objectsWithChild4andOtherChild1.containedIn("otherChild", [childObjects[1]]);
291+
return objectsWithChild4andOtherChild1.find();
292+
}).then(objects => {
293+
// parent2 has child 4 and otherChild 1
294+
expect(objects.length).toEqual(1);
291295
done();
292296
});
293297
});
@@ -652,4 +656,31 @@ describe('Parse.Relation testing', () => {
652656
}));
653657
});
654658
});
659+
660+
it('relations are not bidirectional (regression test for #871)', done => {
661+
let PersonObject = Parse.Object.extend("Person");
662+
let p1 = new PersonObject();
663+
let p2 = new PersonObject();
664+
Parse.Object.saveAll([p1, p2]).then(results => {
665+
let p1 = results[0];
666+
let p2 = results[1];
667+
let relation = p1.relation('relation');
668+
relation.add(p2);
669+
p1.save().then(() => {
670+
let query = new Parse.Query(PersonObject);
671+
query.equalTo('relation', p1);
672+
query.find().then(results => {
673+
expect(results.length).toEqual(0);
674+
675+
let query = new Parse.Query(PersonObject);
676+
query.equalTo('relation', p2);
677+
query.find().then(results => {
678+
expect(results.length).toEqual(1);
679+
expect(results[0].objectId).toEqual(p1.objectId);
680+
done();
681+
});
682+
});
683+
})
684+
});
685+
});
655686
});

spec/QueryTools.spec.js

+14
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,20 @@ describe('matchesQuery', function() {
112112
expect(matchesQuery(obj, q)).toBe(false);
113113
});
114114

115+
it('matches queries with doesNotExist constraint', function() {
116+
var obj = {
117+
id: new Id('Item', 'O1'),
118+
count: 15
119+
};
120+
var q = new Parse.Query('Item');
121+
q.doesNotExist('name');
122+
expect(matchesQuery(obj, q)).toBe(true);
123+
124+
q = new Parse.Query('Item');
125+
q.doesNotExist('count');
126+
expect(matchesQuery(obj, q)).toBe(false);
127+
});
128+
115129
it('matches on equality queries', function() {
116130
var day = new Date();
117131
var location = new Parse.GeoPoint({

0 commit comments

Comments
 (0)