Initial release, parse-server, 2.0.0
This commit is contained in:
15
spec/ExportAdapter.spec.js
Normal file
15
spec/ExportAdapter.spec.js
Normal file
@@ -0,0 +1,15 @@
|
||||
var ExportAdapter = require('../ExportAdapter');
|
||||
|
||||
describe('ExportAdapter', () => {
|
||||
it('can be constructed', (done) => {
|
||||
var database = new ExportAdapter('mongodb://localhost:27017/test',
|
||||
{
|
||||
collectionPrefix: 'test_'
|
||||
});
|
||||
database.connect().then(done, (error) => {
|
||||
console.log('error', error.stack);
|
||||
fail();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
1141
spec/ParseACL.spec.js
Normal file
1141
spec/ParseACL.spec.js
Normal file
File diff suppressed because it is too large
Load Diff
615
spec/ParseAPI.spec.js
Normal file
615
spec/ParseAPI.spec.js
Normal file
@@ -0,0 +1,615 @@
|
||||
// A bunch of different tests are in here - it isn't very thematic.
|
||||
// It would probably be better to refactor them into different files.
|
||||
|
||||
var DatabaseAdapter = require('../DatabaseAdapter');
|
||||
var request = require('request');
|
||||
|
||||
describe('miscellaneous', function() {
|
||||
it('create a GameScore object', function(done) {
|
||||
var obj = new Parse.Object('GameScore');
|
||||
obj.set('score', 1337);
|
||||
obj.save().then(function(obj) {
|
||||
expect(typeof obj.id).toBe('string');
|
||||
expect(typeof obj.createdAt.toGMTString()).toBe('string');
|
||||
done();
|
||||
}, function(err) { console.log(err); });
|
||||
});
|
||||
|
||||
it('get a TestObject', function(done) {
|
||||
create({ 'bloop' : 'blarg' }, function(obj) {
|
||||
var t2 = new TestObject({ objectId: obj.id });
|
||||
t2.fetch({
|
||||
success: function(obj2) {
|
||||
expect(obj2.get('bloop')).toEqual('blarg');
|
||||
expect(obj2.id).toBeTruthy();
|
||||
expect(obj2.id).toEqual(obj.id);
|
||||
done();
|
||||
},
|
||||
error: fail
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('create a valid parse user', function(done) {
|
||||
createTestUser(function(data) {
|
||||
expect(data.id).not.toBeUndefined();
|
||||
expect(data.getSessionToken()).not.toBeUndefined();
|
||||
expect(data.get('password')).toBeUndefined();
|
||||
done();
|
||||
}, function(err) {
|
||||
console.log(err);
|
||||
fail(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('fail to create a duplicate username', function(done) {
|
||||
createTestUser(function(data) {
|
||||
createTestUser(function(data) {
|
||||
fail('Should not have been able to save duplicate username.');
|
||||
}, function(error) {
|
||||
expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('succeed in logging in', function(done) {
|
||||
createTestUser(function(u) {
|
||||
expect(typeof u.id).toEqual('string');
|
||||
|
||||
Parse.User.logIn('test', 'moon-y', {
|
||||
success: function(user) {
|
||||
expect(typeof user.id).toEqual('string');
|
||||
expect(user.get('password')).toBeUndefined();
|
||||
expect(user.getSessionToken()).not.toBeUndefined();
|
||||
Parse.User.logOut();
|
||||
done();
|
||||
}, error: function(error) {
|
||||
fail(error);
|
||||
}
|
||||
});
|
||||
}, fail);
|
||||
});
|
||||
|
||||
it('increment with a user object', function(done) {
|
||||
createTestUser().then((user) => {
|
||||
user.increment('foo');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('test', 'moon-y');
|
||||
}).then((user) => {
|
||||
expect(user.get('foo')).toEqual(1);
|
||||
user.increment('foo');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
Parse.User.logOut();
|
||||
return Parse.User.logIn('test', 'moon-y');
|
||||
}).then((user) => {
|
||||
expect(user.get('foo')).toEqual(2);
|
||||
Parse.User.logOut();
|
||||
done();
|
||||
}, (error) => {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('save various data types', function(done) {
|
||||
var obj = new TestObject();
|
||||
obj.set('date', new Date());
|
||||
obj.set('array', [1, 2, 3]);
|
||||
obj.set('object', {one: 1, two: 2});
|
||||
obj.save().then(() => {
|
||||
var obj2 = new TestObject({objectId: obj.id});
|
||||
return obj2.fetch();
|
||||
}).then((obj2) => {
|
||||
expect(obj2.get('date') instanceof Date).toBe(true);
|
||||
expect(obj2.get('array') instanceof Array).toBe(true);
|
||||
expect(obj2.get('object') instanceof Array).toBe(false);
|
||||
expect(obj2.get('object') instanceof Object).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('query with limit', function(done) {
|
||||
var baz = new TestObject({ foo: 'baz' });
|
||||
var qux = new TestObject({ foo: 'qux' });
|
||||
baz.save().then(() => {
|
||||
return qux.save();
|
||||
}).then(() => {
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.limit(1);
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
done();
|
||||
}, (error) => {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('basic saveAll', function(done) {
|
||||
var alpha = new TestObject({ letter: 'alpha' });
|
||||
var beta = new TestObject({ letter: 'beta' });
|
||||
Parse.Object.saveAll([alpha, beta]).then(() => {
|
||||
expect(alpha.id).toBeTruthy();
|
||||
expect(beta.id).toBeTruthy();
|
||||
return new Parse.Query(TestObject).find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(2);
|
||||
done();
|
||||
}, (error) => {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test cloud function', function(done) {
|
||||
Parse.Cloud.run('hello', {}, function(result) {
|
||||
expect(result).toEqual('Hello world!');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('basic beforeSave rejection', function(done) {
|
||||
var obj = new Parse.Object('BeforeSaveFailure');
|
||||
obj.set('foo', 'bar');
|
||||
obj.save().then(function() {
|
||||
fail('Should not have been able to save BeforeSaveFailure class.');
|
||||
done();
|
||||
}, function(error) {
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('test beforeSave unchanged success', function(done) {
|
||||
var obj = new Parse.Object('BeforeSaveUnchanged');
|
||||
obj.set('foo', 'bar');
|
||||
obj.save().then(function() {
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test beforeSave changed object success', function(done) {
|
||||
var obj = new Parse.Object('BeforeSaveChanged');
|
||||
obj.set('foo', 'bar');
|
||||
obj.save().then(function() {
|
||||
var query = new Parse.Query('BeforeSaveChanged');
|
||||
query.get(obj.id).then(function(objAgain) {
|
||||
expect(objAgain.get('foo')).toEqual('baz');
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test afterSave ran and created an object', function(done) {
|
||||
var obj = new Parse.Object('AfterSaveTest');
|
||||
obj.save();
|
||||
|
||||
setTimeout(function() {
|
||||
var query = new Parse.Query('AfterSaveProof');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(1);
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('test beforeSave happens on update', function(done) {
|
||||
var obj = new Parse.Object('BeforeSaveChanged');
|
||||
obj.set('foo', 'bar');
|
||||
obj.save().then(function() {
|
||||
obj.set('foo', 'bar');
|
||||
return obj.save();
|
||||
}).then(function() {
|
||||
var query = new Parse.Query('BeforeSaveChanged');
|
||||
return query.get(obj.id).then(function(objAgain) {
|
||||
expect(objAgain.get('foo')).toEqual('baz');
|
||||
done();
|
||||
});
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test beforeDelete failure', function(done) {
|
||||
var obj = new Parse.Object('BeforeDeleteFail');
|
||||
var id;
|
||||
obj.set('foo', 'bar');
|
||||
obj.save().then(() => {
|
||||
id = obj.id;
|
||||
return obj.destroy();
|
||||
}).then(() => {
|
||||
fail('obj.destroy() should have failed, but it succeeded');
|
||||
done();
|
||||
}, (error) => {
|
||||
expect(error.code).toEqual(Parse.Error.SCRIPT_FAILED);
|
||||
expect(error.message).toEqual('Nope');
|
||||
|
||||
var objAgain = new Parse.Object('BeforeDeleteFail', {objectId: id});
|
||||
return objAgain.fetch();
|
||||
}).then((objAgain) => {
|
||||
expect(objAgain.get('foo')).toEqual('bar');
|
||||
done();
|
||||
}, (error) => {
|
||||
// We should have been able to fetch the object again
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('test beforeDelete success', function(done) {
|
||||
var obj = new Parse.Object('BeforeDeleteTest');
|
||||
obj.set('foo', 'bar');
|
||||
obj.save().then(function() {
|
||||
return obj.destroy();
|
||||
}).then(function() {
|
||||
var objAgain = new Parse.Object('BeforeDeleteTest', obj.id);
|
||||
return objAgain.fetch().then(fail, done);
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test afterDelete ran and created an object', function(done) {
|
||||
var obj = new Parse.Object('AfterDeleteTest');
|
||||
obj.save().then(function() {
|
||||
obj.destroy();
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
var query = new Parse.Query('AfterDeleteProof');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(1);
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('test save triggers get user', function(done) {
|
||||
var user = new Parse.User();
|
||||
user.set("password", "asdf");
|
||||
user.set("email", "asdf@example.com");
|
||||
user.set("username", "zxcv");
|
||||
user.signUp(null, {
|
||||
success: function() {
|
||||
var obj = new Parse.Object('SaveTriggerUser');
|
||||
obj.save().then(function() {
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('test cloud function return types', function(done) {
|
||||
Parse.Cloud.run('foo').then((result) => {
|
||||
expect(result.object instanceof Parse.Object).toBeTruthy();
|
||||
expect(result.object.className).toEqual('Foo');
|
||||
expect(result.object.get('x')).toEqual(2);
|
||||
var bar = result.object.get('relation');
|
||||
expect(bar instanceof Parse.Object).toBeTruthy();
|
||||
expect(bar.className).toEqual('Bar');
|
||||
expect(bar.get('x')).toEqual(3);
|
||||
expect(Array.isArray(result.array)).toEqual(true);
|
||||
expect(result.array[0] instanceof Parse.Object).toBeTruthy();
|
||||
expect(result.array[0].get('x')).toEqual(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test rest_create_app', function(done) {
|
||||
var appId;
|
||||
Parse._request('POST', 'rest_create_app').then((res) => {
|
||||
expect(typeof res.application_id).toEqual('string');
|
||||
expect(res.master_key).toEqual('master');
|
||||
appId = res.application_id;
|
||||
Parse.initialize(appId, 'unused');
|
||||
var obj = new Parse.Object('TestObject');
|
||||
obj.set('foo', 'bar');
|
||||
return obj.save();
|
||||
}).then(() => {
|
||||
var db = DatabaseAdapter.getDatabaseConnection(appId);
|
||||
return db.mongoFind('TestObject', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0]['foo']).toEqual('bar');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test beforeSave get full object on create and update', function(done) {
|
||||
var triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.beforeSave('GameScore', function(req, res) {
|
||||
var object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
expect(object.get('fooAgain')).toEqual('barAgain');
|
||||
expect(object.id).not.toBeUndefined();
|
||||
expect(object.createdAt).not.toBeUndefined();
|
||||
expect(object.updatedAt).not.toBeUndefined();
|
||||
if (triggerTime == 0) {
|
||||
// Create
|
||||
expect(object.get('foo')).toEqual('bar');
|
||||
} else if (triggerTime == 1) {
|
||||
// Update
|
||||
expect(object.get('foo')).toEqual('baz');
|
||||
} else {
|
||||
res.error();
|
||||
}
|
||||
triggerTime++;
|
||||
res.success();
|
||||
});
|
||||
|
||||
var obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('fooAgain', 'barAgain');
|
||||
obj.save().then(function() {
|
||||
// We only update foo
|
||||
obj.set('foo', 'baz');
|
||||
return obj.save();
|
||||
}).then(function() {
|
||||
// Make sure the checking has been triggered
|
||||
expect(triggerTime).toBe(2);
|
||||
// Clear mock beforeSave
|
||||
delete Parse.Cloud.Triggers.beforeSave.GameScore;
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test afterSave get full object on create and update', function(done) {
|
||||
var triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.afterSave('GameScore', function(req, res) {
|
||||
var object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
expect(object.get('fooAgain')).toEqual('barAgain');
|
||||
expect(object.id).not.toBeUndefined();
|
||||
expect(object.createdAt).not.toBeUndefined();
|
||||
expect(object.updatedAt).not.toBeUndefined();
|
||||
if (triggerTime == 0) {
|
||||
// Create
|
||||
expect(object.get('foo')).toEqual('bar');
|
||||
} else if (triggerTime == 1) {
|
||||
// Update
|
||||
expect(object.get('foo')).toEqual('baz');
|
||||
} else {
|
||||
res.error();
|
||||
}
|
||||
triggerTime++;
|
||||
res.success();
|
||||
});
|
||||
|
||||
var obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('fooAgain', 'barAgain');
|
||||
obj.save().then(function() {
|
||||
// We only update foo
|
||||
obj.set('foo', 'baz');
|
||||
return obj.save();
|
||||
}).then(function() {
|
||||
// Make sure the checking has been triggered
|
||||
expect(triggerTime).toBe(2);
|
||||
// Clear mock afterSave
|
||||
delete Parse.Cloud.Triggers.afterSave.GameScore;
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test beforeSave get original object on update', function(done) {
|
||||
var triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.beforeSave('GameScore', function(req, res) {
|
||||
var object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
expect(object.get('fooAgain')).toEqual('barAgain');
|
||||
expect(object.id).not.toBeUndefined();
|
||||
expect(object.createdAt).not.toBeUndefined();
|
||||
expect(object.updatedAt).not.toBeUndefined();
|
||||
var originalObject = req.original;
|
||||
if (triggerTime == 0) {
|
||||
// Create
|
||||
expect(object.get('foo')).toEqual('bar');
|
||||
// Check the originalObject is undefined
|
||||
expect(originalObject).toBeUndefined();
|
||||
} else if (triggerTime == 1) {
|
||||
// Update
|
||||
expect(object.get('foo')).toEqual('baz');
|
||||
// Check the originalObject
|
||||
expect(originalObject instanceof Parse.Object).toBeTruthy();
|
||||
expect(originalObject.get('fooAgain')).toEqual('barAgain');
|
||||
expect(originalObject.id).not.toBeUndefined();
|
||||
expect(originalObject.createdAt).not.toBeUndefined();
|
||||
expect(originalObject.updatedAt).not.toBeUndefined();
|
||||
expect(originalObject.get('foo')).toEqual('bar');
|
||||
} else {
|
||||
res.error();
|
||||
}
|
||||
triggerTime++;
|
||||
res.success();
|
||||
});
|
||||
|
||||
var obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('fooAgain', 'barAgain');
|
||||
obj.save().then(function() {
|
||||
// We only update foo
|
||||
obj.set('foo', 'baz');
|
||||
return obj.save();
|
||||
}).then(function() {
|
||||
// Make sure the checking has been triggered
|
||||
expect(triggerTime).toBe(2);
|
||||
// Clear mock beforeSave
|
||||
delete Parse.Cloud.Triggers.beforeSave.GameScore;
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test afterSave get original object on update', function(done) {
|
||||
var triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.afterSave('GameScore', function(req, res) {
|
||||
var object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
expect(object.get('fooAgain')).toEqual('barAgain');
|
||||
expect(object.id).not.toBeUndefined();
|
||||
expect(object.createdAt).not.toBeUndefined();
|
||||
expect(object.updatedAt).not.toBeUndefined();
|
||||
var originalObject = req.original;
|
||||
if (triggerTime == 0) {
|
||||
// Create
|
||||
expect(object.get('foo')).toEqual('bar');
|
||||
// Check the originalObject is undefined
|
||||
expect(originalObject).toBeUndefined();
|
||||
} else if (triggerTime == 1) {
|
||||
// Update
|
||||
expect(object.get('foo')).toEqual('baz');
|
||||
// Check the originalObject
|
||||
expect(originalObject instanceof Parse.Object).toBeTruthy();
|
||||
expect(originalObject.get('fooAgain')).toEqual('barAgain');
|
||||
expect(originalObject.id).not.toBeUndefined();
|
||||
expect(originalObject.createdAt).not.toBeUndefined();
|
||||
expect(originalObject.updatedAt).not.toBeUndefined();
|
||||
expect(originalObject.get('foo')).toEqual('bar');
|
||||
} else {
|
||||
res.error();
|
||||
}
|
||||
triggerTime++;
|
||||
res.success();
|
||||
});
|
||||
|
||||
var obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('fooAgain', 'barAgain');
|
||||
obj.save().then(function() {
|
||||
// We only update foo
|
||||
obj.set('foo', 'baz');
|
||||
return obj.save();
|
||||
}).then(function() {
|
||||
// Make sure the checking has been triggered
|
||||
expect(triggerTime).toBe(2);
|
||||
// Clear mock afterSave
|
||||
delete Parse.Cloud.Triggers.afterSave.GameScore;
|
||||
done();
|
||||
}, function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test cloud function error handling', (done) => {
|
||||
// Register a function which will fail
|
||||
Parse.Cloud.define('willFail', (req, res) => {
|
||||
res.error('noway');
|
||||
});
|
||||
Parse.Cloud.run('willFail').then((s) => {
|
||||
fail('Should not have succeeded.');
|
||||
delete Parse.Cloud.Functions['willFail'];
|
||||
done();
|
||||
}, (e) => {
|
||||
expect(e.code).toEqual(141);
|
||||
expect(e.message).toEqual('noway');
|
||||
delete Parse.Cloud.Functions['willFail'];
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on invalid client key', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Client-Key': 'notclient'
|
||||
};
|
||||
request.get({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/TestObject'
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.error).toEqual('unauthorized');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on invalid windows key', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Windows-Key': 'notwindows'
|
||||
};
|
||||
request.get({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/TestObject'
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.error).toEqual('unauthorized');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on invalid javascript key', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'notjavascript'
|
||||
};
|
||||
request.get({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/TestObject'
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.error).toEqual('unauthorized');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on invalid rest api key', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'notrest'
|
||||
};
|
||||
request.get({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/TestObject'
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.error).toEqual('unauthorized');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
375
spec/ParseFile.spec.js
Normal file
375
spec/ParseFile.spec.js
Normal file
@@ -0,0 +1,375 @@
|
||||
// This is a port of the test suite:
|
||||
// hungry/js/test/parse_file_test.js
|
||||
|
||||
var request = require('request');
|
||||
|
||||
var str = "Hello World!";
|
||||
var data = [];
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
data.push(str.charCodeAt(i));
|
||||
}
|
||||
|
||||
describe('Parse.File testing', () => {
|
||||
it('works with REST API', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
request.post({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/files/file.txt',
|
||||
body: 'argle bargle',
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.name).toMatch(/_file.txt$/);
|
||||
expect(b.url).toMatch(/^http:\/\/localhost:8378\/1\/files\/test\/.*file.txt$/);
|
||||
request.get(b.url, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
expect(body).toEqual('argle bargle');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('handles other filetypes', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'image/jpeg',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
request.post({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/files/file.jpg',
|
||||
body: 'argle bargle',
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.name).toMatch(/_file.jpg$/);
|
||||
expect(b.url).toMatch(/^http:\/\/localhost:8378\/1\/files\/.*file.jpg$/);
|
||||
request.get(b.url, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
expect(body).toEqual('argle bargle');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("save file", done => {
|
||||
var file = new Parse.File("hello.txt", data, "text/plain");
|
||||
ok(!file.url());
|
||||
file.save(expectSuccess({
|
||||
success: function(result) {
|
||||
strictEqual(result, file);
|
||||
ok(file.name());
|
||||
ok(file.url());
|
||||
notEqual(file.name(), "hello.txt");
|
||||
done();
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("save file in object", done => {
|
||||
var file = new Parse.File("hello.txt", data, "text/plain");
|
||||
ok(!file.url());
|
||||
file.save(expectSuccess({
|
||||
success: function(result) {
|
||||
strictEqual(result, file);
|
||||
ok(file.name());
|
||||
ok(file.url());
|
||||
notEqual(file.name(), "hello.txt");
|
||||
|
||||
var object = new Parse.Object("TestObject");
|
||||
object.save({
|
||||
file: file
|
||||
}, expectSuccess({
|
||||
success: function(object) {
|
||||
(new Parse.Query("TestObject")).get(object.id, expectSuccess({
|
||||
success: function(objectAgain) {
|
||||
ok(objectAgain.get("file") instanceof Parse.File);
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("save file in object with escaped characters in filename", done => {
|
||||
var file = new Parse.File("hello . txt", data, "text/plain");
|
||||
ok(!file.url());
|
||||
file.save(expectSuccess({
|
||||
success: function(result) {
|
||||
strictEqual(result, file);
|
||||
ok(file.name());
|
||||
ok(file.url());
|
||||
notEqual(file.name(), "hello . txt");
|
||||
|
||||
var object = new Parse.Object("TestObject");
|
||||
object.save({
|
||||
file: file
|
||||
}, expectSuccess({
|
||||
success: function(object) {
|
||||
(new Parse.Query("TestObject")).get(object.id, expectSuccess({
|
||||
success: function(objectAgain) {
|
||||
ok(objectAgain.get("file") instanceof Parse.File);
|
||||
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("autosave file in object", done => {
|
||||
var file = new Parse.File("hello.txt", data, "text/plain");
|
||||
ok(!file.url());
|
||||
var object = new Parse.Object("TestObject");
|
||||
object.save({
|
||||
file: file
|
||||
}, expectSuccess({
|
||||
success: function(object) {
|
||||
(new Parse.Query("TestObject")).get(object.id, expectSuccess({
|
||||
success: function(objectAgain) {
|
||||
file = objectAgain.get("file");
|
||||
ok(file instanceof Parse.File);
|
||||
ok(file.name());
|
||||
ok(file.url());
|
||||
notEqual(file.name(), "hello.txt");
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("autosave file in object in object", done => {
|
||||
var file = new Parse.File("hello.txt", data, "text/plain");
|
||||
ok(!file.url());
|
||||
|
||||
var child = new Parse.Object("Child");
|
||||
child.set("file", file);
|
||||
|
||||
var parent = new Parse.Object("Parent");
|
||||
parent.set("child", child);
|
||||
|
||||
parent.save(expectSuccess({
|
||||
success: function(parent) {
|
||||
var query = new Parse.Query("Parent");
|
||||
query.include("child");
|
||||
query.get(parent.id, expectSuccess({
|
||||
success: function(parentAgain) {
|
||||
var childAgain = parentAgain.get("child");
|
||||
file = childAgain.get("file");
|
||||
ok(file instanceof Parse.File);
|
||||
ok(file.name());
|
||||
ok(file.url());
|
||||
notEqual(file.name(), "hello.txt");
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("saving an already saved file", done => {
|
||||
var file = new Parse.File("hello.txt", data, "text/plain");
|
||||
ok(!file.url());
|
||||
file.save(expectSuccess({
|
||||
success: function(result) {
|
||||
strictEqual(result, file);
|
||||
ok(file.name());
|
||||
ok(file.url());
|
||||
notEqual(file.name(), "hello.txt");
|
||||
var previousName = file.name();
|
||||
|
||||
file.save(expectSuccess({
|
||||
success: function() {
|
||||
equal(file.name(), previousName);
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("two saves at the same time", done => {
|
||||
var file = new Parse.File("hello.txt", data, "text/plain");
|
||||
|
||||
var firstName;
|
||||
var secondName;
|
||||
|
||||
var firstSave = file.save().then(function() { firstName = file.name(); });
|
||||
var secondSave = file.save().then(function() { secondName = file.name(); });
|
||||
|
||||
Parse.Promise.when(firstSave, secondSave).then(function() {
|
||||
equal(firstName, secondName);
|
||||
done();
|
||||
}, function(error) {
|
||||
ok(false, error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("file toJSON testing", done => {
|
||||
var file = new Parse.File("hello.txt", data, "text/plain");
|
||||
ok(!file.url());
|
||||
var object = new Parse.Object("TestObject");
|
||||
object.save({
|
||||
file: file
|
||||
}, expectSuccess({
|
||||
success: function(obj) {
|
||||
ok(object.toJSON().file.url);
|
||||
done();
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("content-type used with no extension", done => {
|
||||
var headers = {
|
||||
'Content-Type': 'text/html',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
request.post({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/files/file',
|
||||
body: 'fee fi fo',
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.name).toMatch(/\.html$/);
|
||||
request.get(b.url, (error, response, body) => {
|
||||
expect(response.headers['content-type']).toMatch(/^text\/html/);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("filename is url encoded", done => {
|
||||
var headers = {
|
||||
'Content-Type': 'text/html',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
request.post({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/files/hello world.txt',
|
||||
body: 'oh emm gee',
|
||||
}, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
var b = JSON.parse(body);
|
||||
expect(b.url).toMatch(/hello%20world/);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('supports array of files', done => {
|
||||
var file = {
|
||||
__type: 'File',
|
||||
url: 'http://meep.meep',
|
||||
name: 'meep'
|
||||
};
|
||||
var files = [file, file];
|
||||
var obj = new Parse.Object('FilesArrayTest');
|
||||
obj.set('files', files);
|
||||
obj.save().then(() => {
|
||||
var query = new Parse.Query('FilesArrayTest');
|
||||
return query.first();
|
||||
}).then((result) => {
|
||||
var filesAgain = result.get('files');
|
||||
expect(filesAgain.length).toEqual(2);
|
||||
expect(filesAgain[0].name()).toEqual('meep');
|
||||
expect(filesAgain[0].url()).toEqual('http://meep.meep');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('validates filename characters', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'text/plain',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
request.post({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/files/di$avowed.txt',
|
||||
body: 'will fail',
|
||||
}, (error, response, body) => {
|
||||
var b = JSON.parse(body);
|
||||
expect(b.code).toEqual(122);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('validates filename length', done => {
|
||||
var headers = {
|
||||
'Content-Type': 'text/plain',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
var fileName = 'Onceuponamidnightdrearywhileiponderedweak' +
|
||||
'andwearyOveramanyquaintandcuriousvolumeof' +
|
||||
'forgottenloreWhileinoddednearlynappingsud' +
|
||||
'denlytherecameatapping';
|
||||
request.post({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/files/' + fileName,
|
||||
body: 'will fail',
|
||||
}, (error, response, body) => {
|
||||
var b = JSON.parse(body);
|
||||
expect(b.code).toEqual(122);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('supports a dictionary with file', done => {
|
||||
var file = {
|
||||
__type: 'File',
|
||||
url: 'http://meep.meep',
|
||||
name: 'meep'
|
||||
};
|
||||
var dict = {
|
||||
file: file
|
||||
};
|
||||
var obj = new Parse.Object('FileObjTest');
|
||||
obj.set('obj', dict);
|
||||
obj.save().then(() => {
|
||||
var query = new Parse.Query('FileObjTest');
|
||||
return query.first();
|
||||
}).then((result) => {
|
||||
var dictAgain = result.get('obj');
|
||||
expect(typeof dictAgain).toEqual('object');
|
||||
var fileAgain = dictAgain['file'];
|
||||
expect(fileAgain.name()).toEqual('meep');
|
||||
expect(fileAgain.url()).toEqual('http://meep.meep');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('creates correct url for old files hosted on parse', done => {
|
||||
var file = {
|
||||
__type: 'File',
|
||||
url: 'http://irrelevant.elephant/',
|
||||
name: 'tfss-123.txt'
|
||||
};
|
||||
var obj = new Parse.Object('OldFileTest');
|
||||
obj.set('oldfile', file);
|
||||
obj.save().then(() => {
|
||||
var query = new Parse.Query('OldFileTest');
|
||||
return query.first();
|
||||
}).then((result) => {
|
||||
var fileAgain = result.get('oldfile');
|
||||
expect(fileAgain.url()).toEqual(
|
||||
'http://files.parsetfss.com/test/tfss-123.txt'
|
||||
);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
290
spec/ParseGeoPoint.spec.js
Normal file
290
spec/ParseGeoPoint.spec.js
Normal file
@@ -0,0 +1,290 @@
|
||||
// This is a port of the test suite:
|
||||
// hungry/js/test/parse_geo_point_test.js
|
||||
|
||||
var TestObject = Parse.Object.extend('TestObject');
|
||||
|
||||
describe('Parse.GeoPoint testing', () => {
|
||||
it('geo point roundtrip', (done) => {
|
||||
var point = new Parse.GeoPoint(44.0, -11.0);
|
||||
var obj = new TestObject();
|
||||
obj.set('location', point);
|
||||
obj.set('name', 'Ferndale');
|
||||
obj.save(null, {
|
||||
success: function() {
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 1);
|
||||
var pointAgain = results[0].get('location');
|
||||
ok(pointAgain);
|
||||
equal(pointAgain.latitude, 44.0);
|
||||
equal(pointAgain.longitude, -11.0);
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('geo point exception two fields', (done) => {
|
||||
var point = new Parse.GeoPoint(20, 20);
|
||||
var obj = new TestObject();
|
||||
obj.set('locationOne', point);
|
||||
obj.set('locationTwo', point);
|
||||
obj.save().then(() => {
|
||||
fail('expected error');
|
||||
}, (err) => {
|
||||
equal(err.code, Parse.Error.INCORRECT_TYPE);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('geo line', (done) => {
|
||||
var line = [];
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
var obj = new TestObject();
|
||||
var point = new Parse.GeoPoint(i * 4.0 - 12.0, i * 3.2 - 11.0);
|
||||
obj.set('location', point);
|
||||
obj.set('construct', 'line');
|
||||
obj.set('seq', i);
|
||||
line.push(obj);
|
||||
}
|
||||
Parse.Object.saveAll(line, {
|
||||
success: function() {
|
||||
var query = new Parse.Query(TestObject);
|
||||
var point = new Parse.GeoPoint(24, 19);
|
||||
query.equalTo('construct', 'line');
|
||||
query.withinMiles('location', point, 10000);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 10);
|
||||
equal(results[0].get('seq'), 9);
|
||||
equal(results[3].get('seq'), 6);
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance large', (done) => {
|
||||
var objects = [];
|
||||
[0, 1, 2].map(function(i) {
|
||||
var obj = new TestObject();
|
||||
var point = new Parse.GeoPoint(0.0, i * 45.0);
|
||||
obj.set('location', point);
|
||||
obj.set('index', i);
|
||||
objects.push(obj);
|
||||
});
|
||||
Parse.Object.saveAll(objects).then((list) => {
|
||||
var query = new Parse.Query(TestObject);
|
||||
var point = new Parse.GeoPoint(1.0, -1.0);
|
||||
query.withinRadians('location', point, 3.14);
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
equal(results.length, 3);
|
||||
done();
|
||||
}, (err) => {
|
||||
console.log(err);
|
||||
fail();
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance medium', (done) => {
|
||||
var objects = [];
|
||||
[0, 1, 2].map(function(i) {
|
||||
var obj = new TestObject();
|
||||
var point = new Parse.GeoPoint(0.0, i * 45.0);
|
||||
obj.set('location', point);
|
||||
obj.set('index', i);
|
||||
objects.push(obj);
|
||||
});
|
||||
Parse.Object.saveAll(objects, function(list) {
|
||||
var query = new Parse.Query(TestObject);
|
||||
var point = new Parse.GeoPoint(1.0, -1.0);
|
||||
query.withinRadians('location', point, 3.14 * 0.5);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 2);
|
||||
equal(results[0].get('index'), 0);
|
||||
equal(results[1].get('index'), 1);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance small', (done) => {
|
||||
var objects = [];
|
||||
[0, 1, 2].map(function(i) {
|
||||
var obj = new TestObject();
|
||||
var point = new Parse.GeoPoint(0.0, i * 45.0);
|
||||
obj.set('location', point);
|
||||
obj.set('index', i);
|
||||
objects.push(obj);
|
||||
});
|
||||
Parse.Object.saveAll(objects, function(list) {
|
||||
var query = new Parse.Query(TestObject);
|
||||
var point = new Parse.GeoPoint(1.0, -1.0);
|
||||
query.withinRadians('location', point, 3.14 * 0.25);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 1);
|
||||
equal(results[0].get('index'), 0);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var makeSomeGeoPoints = function(callback) {
|
||||
var sacramento = new TestObject();
|
||||
sacramento.set('location', new Parse.GeoPoint(38.52, -121.50));
|
||||
sacramento.set('name', 'Sacramento');
|
||||
|
||||
var honolulu = new TestObject();
|
||||
honolulu.set('location', new Parse.GeoPoint(21.35, -157.93));
|
||||
honolulu.set('name', 'Honolulu');
|
||||
|
||||
var sf = new TestObject();
|
||||
sf.set('location', new Parse.GeoPoint(37.75, -122.68));
|
||||
sf.set('name', 'San Francisco');
|
||||
|
||||
Parse.Object.saveAll([sacramento, sf, honolulu], callback);
|
||||
};
|
||||
|
||||
it('geo max distance in km everywhere', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinKilometers('location', sfo, 4000.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 3);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance in km california', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinKilometers('location', sfo, 3700.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 2);
|
||||
equal(results[0].get('name'), 'San Francisco');
|
||||
equal(results[1].get('name'), 'Sacramento');
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance in km bay area', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinKilometers('location', sfo, 100.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 1);
|
||||
equal(results[0].get('name'), 'San Francisco');
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance in km mid peninsula', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinKilometers('location', sfo, 10.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 0);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance in miles everywhere', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinMiles('location', sfo, 2500.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 3);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance in miles california', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinMiles('location', sfo, 2200.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 2);
|
||||
equal(results[0].get('name'), 'San Francisco');
|
||||
equal(results[1].get('name'), 'Sacramento');
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance in miles bay area', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinMiles('location', sfo, 75.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 1);
|
||||
equal(results[0].get('name'), 'San Francisco');
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('geo max distance in miles mid peninsula', (done) => {
|
||||
makeSomeGeoPoints(function(list) {
|
||||
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinMiles('location', sfo, 10.0);
|
||||
query.find({
|
||||
success: function(results) {
|
||||
equal(results.length, 0);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('works with geobox queries', (done) => {
|
||||
var inSF = new Parse.GeoPoint(37.75, -122.4);
|
||||
var southwestOfSF = new Parse.GeoPoint(37.708813, -122.526398);
|
||||
var northeastOfSF = new Parse.GeoPoint(37.822802, -122.373962);
|
||||
|
||||
var object = new TestObject();
|
||||
object.set('point', inSF);
|
||||
object.save().then(() => {
|
||||
var query = new Parse.Query(TestObject);
|
||||
query.withinGeoBox('point', southwestOfSF, northeastOfSF);
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
equal(results.length, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
777
spec/ParseInstallation.spec.js
Normal file
777
spec/ParseInstallation.spec.js
Normal file
@@ -0,0 +1,777 @@
|
||||
// These tests check the Installations functionality of the REST API.
|
||||
// Ported from installation_collection_test.go
|
||||
|
||||
var auth = require('../Auth');
|
||||
var cache = require('../cache');
|
||||
var Config = require('../Config');
|
||||
var DatabaseAdapter = require('../DatabaseAdapter');
|
||||
var Parse = require('parse/node').Parse;
|
||||
var rest = require('../rest');
|
||||
|
||||
var config = new Config('test');
|
||||
var database = DatabaseAdapter.getDatabaseConnection('test');
|
||||
|
||||
describe('Installations', () => {
|
||||
|
||||
it('creates an android installation with ids', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var device = 'android';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var obj = results[0];
|
||||
expect(obj.installationId).toEqual(installId);
|
||||
expect(obj.deviceType).toEqual(device);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('creates an ios installation with ids', (done) => {
|
||||
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var device = 'ios';
|
||||
var input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var obj = results[0];
|
||||
expect(obj.deviceToken).toEqual(t);
|
||||
expect(obj.deviceType).toEqual(device);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('creates an embedded installation with ids', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var device = 'embedded';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var obj = results[0];
|
||||
expect(obj.installationId).toEqual(installId);
|
||||
expect(obj.deviceType).toEqual(device);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('creates an android installation with all fields', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var device = 'android';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device,
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var obj = results[0];
|
||||
expect(obj.installationId).toEqual(installId);
|
||||
expect(obj.deviceType).toEqual(device);
|
||||
expect(typeof obj.channels).toEqual('object');
|
||||
expect(obj.channels.length).toEqual(2);
|
||||
expect(obj.channels[0]).toEqual('foo');
|
||||
expect(obj.channels[1]).toEqual('bar');
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('creates an ios installation with all fields', (done) => {
|
||||
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var device = 'ios';
|
||||
var input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': device,
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var obj = results[0];
|
||||
expect(obj.deviceToken).toEqual(t);
|
||||
expect(obj.deviceType).toEqual(device);
|
||||
expect(typeof obj.channels).toEqual('object');
|
||||
expect(obj.channels.length).toEqual(2);
|
||||
expect(obj.channels[0]).toEqual('foo');
|
||||
expect(obj.channels[1]).toEqual('bar');
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('fails with missing ids', (done) => {
|
||||
var input = {
|
||||
'deviceType': 'android',
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
fail('Should not have been able to create an Installation.');
|
||||
done();
|
||||
}).catch((error) => {
|
||||
expect(error.code).toEqual(135);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails for android with device token', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var device = 'android';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device,
|
||||
'deviceToken': t,
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
fail('Should not have been able to create an Installation.');
|
||||
done();
|
||||
}).catch((error) => {
|
||||
expect(error.code).toEqual(114);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails for android with missing type', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
fail('Should not have been able to create an Installation.');
|
||||
done();
|
||||
}).catch((error) => {
|
||||
expect(error.code).toEqual(135);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('creates an object with custom fields', (done) => {
|
||||
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios',
|
||||
'channels': ['foo', 'bar'],
|
||||
'custom': 'allowed'
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var obj = results[0];
|
||||
expect(obj.custom).toEqual('allowed');
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
// Note: did not port test 'TestObjectIDForIdentifiers'
|
||||
|
||||
it('merging when installationId already exists', (done) => {
|
||||
var installId1 = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var installId2 = '12345678-abcd-abcd-abcd-123456789abd';
|
||||
var input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios',
|
||||
'installationId': installId1,
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
var firstObject;
|
||||
var secondObject;
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
firstObject = results[0];
|
||||
delete input.deviceToken;
|
||||
delete input.channels;
|
||||
input['foo'] = 'bar';
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
secondObject = results[0];
|
||||
expect(firstObject._id).toEqual(secondObject._id);
|
||||
expect(secondObject.channels.length).toEqual(2);
|
||||
expect(secondObject.foo).toEqual('bar');
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('merging when two objects both only have one id', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input1 = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
var input2 = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
var input3 = {
|
||||
'deviceToken': t,
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
var firstObject;
|
||||
var secondObject;
|
||||
rest.create(config, auth.nobody(config), '_Installation', input1)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
firstObject = results[0];
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input2);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(2);
|
||||
if (results[0]['_id'] == firstObject._id) {
|
||||
secondObject = results[1];
|
||||
} else {
|
||||
secondObject = results[0];
|
||||
}
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input3);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0]['_id']).toEqual(secondObject._id);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
notWorking('creating multiple devices with same device token works', (done) => {
|
||||
var installId1 = '11111111-abcd-abcd-abcd-123456789abc';
|
||||
var installId2 = '22222222-abcd-abcd-abcd-123456789abc';
|
||||
var installId3 = '33333333-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId1,
|
||||
'deviceType': 'ios',
|
||||
'deviceToken': t
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
input.installationId = installId2;
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
input.installationId = installId3;
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation',
|
||||
{installationId: installId1}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
return database.mongoFind('_Installation',
|
||||
{installationId: installId2}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
return database.mongoFind('_Installation',
|
||||
{installationId: installId3}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('updating with new channels', (done) => {
|
||||
var input = {
|
||||
'installationId': '12345678-abcd-abcd-abcd-123456789abc',
|
||||
'deviceType': 'android',
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var id = results[0]['_id'];
|
||||
var update = {
|
||||
'channels': ['baz']
|
||||
};
|
||||
return rest.update(config, auth.nobody(config),
|
||||
'_Installation', id, update);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].channels.length).toEqual(1);
|
||||
expect(results[0].channels[0]).toEqual('baz');
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('update android fails with new installation id', (done) => {
|
||||
var installId1 = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var installId2 = '87654321-abcd-abcd-abcd-123456789abc';
|
||||
var input = {
|
||||
'installationId': installId1,
|
||||
'deviceType': 'android',
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'installationId': installId2
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
fail('Updating the installation should have failed.');
|
||||
done();
|
||||
}).catch((error) => {
|
||||
expect(error.code).toEqual(136);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update ios fails with new deviceToken and no installationId', (done) => {
|
||||
var a = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var b = '91433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var input = {
|
||||
'deviceToken': a,
|
||||
'deviceType': 'ios',
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'deviceToken': b
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
fail('Updating the installation should have failed.');
|
||||
}).catch((error) => {
|
||||
expect(error.code).toEqual(136);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update ios updates device token', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var u = '91433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios',
|
||||
'deviceToken': t,
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'installationId': installId,
|
||||
'deviceToken': u,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].deviceToken).toEqual(u);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update fails to change deviceType', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'android',
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
fail('Should not have been able to update Installation.');
|
||||
done();
|
||||
}).catch((error) => {
|
||||
expect(error.code).toEqual(136);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update android with custom field', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'android',
|
||||
'channels': ['foo', 'bar']
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'custom': 'allowed'
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0]['custom']).toEqual('allowed');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update ios device token with duplicate device token', (done) => {
|
||||
var installId1 = '11111111-abcd-abcd-abcd-123456789abc';
|
||||
var installId2 = '22222222-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId1,
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
var firstObject;
|
||||
var secondObject;
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
input = {
|
||||
'installationId': installId2,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation',
|
||||
{installationId: installId1}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
firstObject = results[0];
|
||||
return database.mongoFind('_Installation',
|
||||
{installationId: installId2}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
secondObject = results[0];
|
||||
// Update second installation to conflict with first installation id
|
||||
input = {
|
||||
'installationId': installId2,
|
||||
'deviceToken': t
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
secondObject._id, input);
|
||||
}).then(() => {
|
||||
// The first object should have been deleted
|
||||
return database.mongoFind('_Installation', {_id: firstObject._id}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(0);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
notWorking('update ios device token with duplicate token different app', (done) => {
|
||||
var installId1 = '11111111-abcd-abcd-abcd-123456789abc';
|
||||
var installId2 = '22222222-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId1,
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios',
|
||||
'appIdentifier': 'foo'
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
input.installationId = installId2;
|
||||
input.appIdentifier = 'bar';
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
// The first object should have been deleted during merge
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].installationId).toEqual(installId2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update ios token and channels', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'deviceToken': t,
|
||||
'channels': []
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].installationId).toEqual(installId);
|
||||
expect(results[0].deviceToken).toEqual(t);
|
||||
expect(results[0].channels.length).toEqual(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update ios linking two existing objects', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation',
|
||||
{deviceToken: t}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'deviceToken': t,
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].installationId).toEqual(installId);
|
||||
expect(results[0].deviceToken).toEqual(t);
|
||||
expect(results[0].deviceType).toEqual('ios');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update is linking two existing objects w/ increment', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation',
|
||||
{deviceToken: t}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'deviceToken': t,
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios',
|
||||
'score': {
|
||||
'__op': 'Increment',
|
||||
'amount': 1
|
||||
}
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
results[0]['_id'], input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].installationId).toEqual(installId);
|
||||
expect(results[0].deviceToken).toEqual(t);
|
||||
expect(results[0].deviceType).toEqual('ios');
|
||||
expect(results[0].score).toEqual(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update is linking two existing with installation id', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
var installObj;
|
||||
var tokenObj;
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
installObj = results[0];
|
||||
input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {deviceToken: t}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
tokenObj = results[0];
|
||||
input = {
|
||||
'installationId': installId,
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
installObj._id, input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {_id: tokenObj._id}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].installationId).toEqual(installId);
|
||||
expect(results[0].deviceToken).toEqual(t);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('update is linking two existing with installation id w/ op', (done) => {
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var input = {
|
||||
'installationId': installId,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
var installObj;
|
||||
var tokenObj;
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
installObj = results[0];
|
||||
input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {deviceToken: t}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
tokenObj = results[0];
|
||||
input = {
|
||||
'installationId': installId,
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios',
|
||||
'score': {
|
||||
'__op': 'Increment',
|
||||
'amount': 1
|
||||
}
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation',
|
||||
installObj._id, input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {_id: tokenObj._id}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].installationId).toEqual(installId);
|
||||
expect(results[0].deviceToken).toEqual(t);
|
||||
expect(results[0].score).toEqual(1);
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
it('ios merge existing same token no installation id', (done) => {
|
||||
// Test creating installation when there is an existing object with the
|
||||
// same device token but no installation ID. This is possible when
|
||||
// developers import device tokens from another push provider; the import
|
||||
// process does not generate installation IDs. When they later integrate
|
||||
// the Parse SDK, their app is going to save the installation. This save
|
||||
// op will have a client-generated installation ID as well as a device
|
||||
// token. At this point, if the device token matches the originally-
|
||||
// imported installation, then we should reuse the existing installation
|
||||
// object in case the developer already added additional fields via Data
|
||||
// Browser or REST API (e.g. channel targeting info).
|
||||
var t = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
var installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
var input = {
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
input = {
|
||||
'installationId': installId,
|
||||
'deviceToken': t,
|
||||
'deviceType': 'ios'
|
||||
};
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
}).then(() => {
|
||||
return database.mongoFind('_Installation', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].deviceToken).toEqual(t);
|
||||
expect(results[0].installationId).toEqual(installId);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Look at additional tests from installation_collection_test.go:882
|
||||
// TODO: Do we need to support _tombstone disabling of installations?
|
||||
// TODO: Test deletion, badge increments
|
||||
|
||||
});
|
||||
1739
spec/ParseObject.spec.js
Normal file
1739
spec/ParseObject.spec.js
Normal file
File diff suppressed because it is too large
Load Diff
2075
spec/ParseQuery.spec.js
Normal file
2075
spec/ParseQuery.spec.js
Normal file
File diff suppressed because it is too large
Load Diff
338
spec/ParseRelation.spec.js
Normal file
338
spec/ParseRelation.spec.js
Normal file
@@ -0,0 +1,338 @@
|
||||
// This is a port of the test suite:
|
||||
// hungry/js/test/parse_relation_test.js
|
||||
|
||||
var ChildObject = Parse.Object.extend({className: "ChildObject"});
|
||||
var ParentObject = Parse.Object.extend({className: "ParentObject"});
|
||||
|
||||
describe('Parse.Relation testing', () => {
|
||||
it("simple add and remove relation", (done) => {
|
||||
var child = new ChildObject();
|
||||
child.set("x", 2);
|
||||
var parent = new ParentObject();
|
||||
parent.set("x", 4);
|
||||
var relation = parent.relation("child");
|
||||
|
||||
child.save().then(() => {
|
||||
relation.add(child);
|
||||
return parent.save();
|
||||
}, (e) => {
|
||||
fail(e);
|
||||
}).then(() => {
|
||||
return relation.query().find();
|
||||
}).then((list) => {
|
||||
equal(list.length, 1,
|
||||
"Should have gotten one element back");
|
||||
equal(list[0].id, child.id,
|
||||
"Should have gotten the right value");
|
||||
ok(!parent.dirty("child"),
|
||||
"The relation should not be dirty");
|
||||
|
||||
relation.remove(child);
|
||||
return parent.save();
|
||||
}).then(() => {
|
||||
return relation.query().find();
|
||||
}).then((list) => {
|
||||
equal(list.length, 0,
|
||||
"Delete should have worked");
|
||||
ok(!parent.dirty("child"),
|
||||
"The relation should not be dirty");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("query relation without schema", (done) => {
|
||||
var ChildObject = Parse.Object.extend("ChildObject");
|
||||
var childObjects = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
childObjects.push(new ChildObject({x:i}));
|
||||
};
|
||||
|
||||
Parse.Object.saveAll(childObjects, expectSuccess({
|
||||
success: function(list) {
|
||||
var ParentObject = Parse.Object.extend("ParentObject");
|
||||
var parent = new ParentObject();
|
||||
parent.set("x", 4);
|
||||
var relation = parent.relation("child");
|
||||
relation.add(childObjects[0]);
|
||||
parent.save(null, expectSuccess({
|
||||
success: function() {
|
||||
var parentAgain = new ParentObject();
|
||||
parentAgain.id = parent.id;
|
||||
var relation = parentAgain.relation("child");
|
||||
relation.query().find(expectSuccess({
|
||||
success: function(list) {
|
||||
equal(list.length, 1,
|
||||
"Should have gotten one element back");
|
||||
equal(list[0].id, childObjects[0].id,
|
||||
"Should have gotten the right value");
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("relations are constructed right from query", (done) => {
|
||||
|
||||
var ChildObject = Parse.Object.extend("ChildObject");
|
||||
var childObjects = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
childObjects.push(new ChildObject({x: i}));
|
||||
}
|
||||
|
||||
Parse.Object.saveAll(childObjects, {
|
||||
success: function(list) {
|
||||
var ParentObject = Parse.Object.extend("ParentObject");
|
||||
var parent = new ParentObject();
|
||||
parent.set("x", 4);
|
||||
var relation = parent.relation("child");
|
||||
relation.add(childObjects[0]);
|
||||
parent.save(null, {
|
||||
success: function() {
|
||||
var query = new Parse.Query(ParentObject);
|
||||
query.get(parent.id, {
|
||||
success: function(object) {
|
||||
var relationAgain = object.relation("child");
|
||||
relationAgain.query().find({
|
||||
success: function(list) {
|
||||
equal(list.length, 1,
|
||||
"Should have gotten one element back");
|
||||
equal(list[0].id, childObjects[0].id,
|
||||
"Should have gotten the right value");
|
||||
ok(!parent.dirty("child"),
|
||||
"The relation should not be dirty");
|
||||
done();
|
||||
},
|
||||
error: function(list) {
|
||||
ok(false, "This shouldn't have failed");
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("compound add and remove relation", (done) => {
|
||||
var ChildObject = Parse.Object.extend("ChildObject");
|
||||
var childObjects = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
childObjects.push(new ChildObject({x: i}));
|
||||
}
|
||||
|
||||
var parent;
|
||||
var relation;
|
||||
|
||||
Parse.Object.saveAll(childObjects).then(function(list) {
|
||||
var ParentObject = Parse.Object.extend('ParentObject');
|
||||
parent = new ParentObject();
|
||||
parent.set('x', 4);
|
||||
relation = parent.relation('child');
|
||||
relation.add(childObjects[0]);
|
||||
relation.add(childObjects[1]);
|
||||
relation.remove(childObjects[0]);
|
||||
relation.add(childObjects[2]);
|
||||
return parent.save();
|
||||
}).then(function() {
|
||||
return relation.query().find();
|
||||
}).then(function(list) {
|
||||
equal(list.length, 2, 'Should have gotten two elements back');
|
||||
ok(!parent.dirty('child'), 'The relation should not be dirty');
|
||||
relation.remove(childObjects[1]);
|
||||
relation.remove(childObjects[2]);
|
||||
relation.add(childObjects[1]);
|
||||
relation.add(childObjects[0]);
|
||||
return parent.save();
|
||||
}).then(function() {
|
||||
return relation.query().find();
|
||||
}).then(function(list) {
|
||||
equal(list.length, 2, 'Deletes and then adds should have worked');
|
||||
ok(!parent.dirty('child'), 'The relation should not be dirty');
|
||||
done();
|
||||
}, function(err) {
|
||||
ok(false, err.message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("queries with relations", (done) => {
|
||||
|
||||
var ChildObject = Parse.Object.extend("ChildObject");
|
||||
var childObjects = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
childObjects.push(new ChildObject({x: i}));
|
||||
}
|
||||
|
||||
Parse.Object.saveAll(childObjects, {
|
||||
success: function() {
|
||||
var ParentObject = Parse.Object.extend("ParentObject");
|
||||
var parent = new ParentObject();
|
||||
parent.set("x", 4);
|
||||
var relation = parent.relation("child");
|
||||
relation.add(childObjects[0]);
|
||||
relation.add(childObjects[1]);
|
||||
relation.add(childObjects[2]);
|
||||
parent.save(null, {
|
||||
success: function() {
|
||||
var query = relation.query();
|
||||
query.equalTo("x", 2);
|
||||
query.find({
|
||||
success: function(list) {
|
||||
equal(list.length, 1,
|
||||
"There should only be one element");
|
||||
ok(list[0] instanceof ChildObject,
|
||||
"Should be of type ChildObject");
|
||||
equal(list[0].id, childObjects[2].id,
|
||||
"We should have gotten back the right result");
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("queries on relation fields", (done) => {
|
||||
var ChildObject = Parse.Object.extend("ChildObject");
|
||||
var childObjects = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
childObjects.push(new ChildObject({x: i}));
|
||||
}
|
||||
|
||||
Parse.Object.saveAll(childObjects, {
|
||||
success: function() {
|
||||
var ParentObject = Parse.Object.extend("ParentObject");
|
||||
var parent = new ParentObject();
|
||||
parent.set("x", 4);
|
||||
var relation = parent.relation("child");
|
||||
relation.add(childObjects[0]);
|
||||
relation.add(childObjects[1]);
|
||||
relation.add(childObjects[2]);
|
||||
var parent2 = new ParentObject();
|
||||
parent2.set("x", 3);
|
||||
var relation2 = parent2.relation("child");
|
||||
relation2.add(childObjects[4]);
|
||||
relation2.add(childObjects[5]);
|
||||
relation2.add(childObjects[6]);
|
||||
var parents = [];
|
||||
parents.push(parent);
|
||||
parents.push(parent2);
|
||||
Parse.Object.saveAll(parents, {
|
||||
success: function() {
|
||||
var query = new Parse.Query(ParentObject);
|
||||
var objects = [];
|
||||
objects.push(childObjects[4]);
|
||||
objects.push(childObjects[9]);
|
||||
query.containedIn("child", objects);
|
||||
query.find({
|
||||
success: function(list) {
|
||||
equal(list.length, 1, "There should be only one result");
|
||||
equal(list[0].id, parent2.id,
|
||||
"Should have gotten back the right result");
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("Get query on relation using un-fetched parent object", (done) => {
|
||||
// Setup data model
|
||||
var Wheel = Parse.Object.extend('Wheel');
|
||||
var Car = Parse.Object.extend('Car');
|
||||
var origWheel = new Wheel();
|
||||
origWheel.save().then(function() {
|
||||
var car = new Car();
|
||||
var relation = car.relation('wheels');
|
||||
relation.add(origWheel);
|
||||
return car.save();
|
||||
}).then(function(car) {
|
||||
// Test starts here.
|
||||
// Create an un-fetched shell car object
|
||||
var unfetchedCar = new Car();
|
||||
unfetchedCar.id = car.id;
|
||||
var relation = unfetchedCar.relation('wheels');
|
||||
var query = relation.query();
|
||||
|
||||
// Parent object is un-fetched, so this will call /1/classes/Car instead
|
||||
// of /1/classes/Wheel and pass { "redirectClassNameForKey":"wheels" }.
|
||||
return query.get(origWheel.id);
|
||||
}).then(function(wheel) {
|
||||
// Make sure this is Wheel and not Car.
|
||||
strictEqual(wheel.className, 'Wheel');
|
||||
strictEqual(wheel.id, origWheel.id);
|
||||
}).then(function() {
|
||||
done();
|
||||
},function(err) {
|
||||
ok(false, 'unexpected error: ' + JSON.stringify(err));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Find query on relation using un-fetched parent object", (done) => {
|
||||
// Setup data model
|
||||
var Wheel = Parse.Object.extend('Wheel');
|
||||
var Car = Parse.Object.extend('Car');
|
||||
var origWheel = new Wheel();
|
||||
origWheel.save().then(function() {
|
||||
var car = new Car();
|
||||
var relation = car.relation('wheels');
|
||||
relation.add(origWheel);
|
||||
return car.save();
|
||||
}).then(function(car) {
|
||||
// Test starts here.
|
||||
// Create an un-fetched shell car object
|
||||
var unfetchedCar = new Car();
|
||||
unfetchedCar.id = car.id;
|
||||
var relation = unfetchedCar.relation('wheels');
|
||||
var query = relation.query();
|
||||
|
||||
// Parent object is un-fetched, so this will call /1/classes/Car instead
|
||||
// of /1/classes/Wheel and pass { "redirectClassNameForKey":"wheels" }.
|
||||
return query.find(origWheel.id);
|
||||
}).then(function(results) {
|
||||
// Make sure this is Wheel and not Car.
|
||||
var wheel = results[0];
|
||||
strictEqual(wheel.className, 'Wheel');
|
||||
strictEqual(wheel.id, origWheel.id);
|
||||
}).then(function() {
|
||||
done();
|
||||
},function(err) {
|
||||
ok(false, 'unexpected error: ' + JSON.stringify(err));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Find objects with a related object using equalTo', (done) => {
|
||||
// Setup the objects
|
||||
var Card = Parse.Object.extend('Card');
|
||||
var House = Parse.Object.extend('House');
|
||||
var card = new Card();
|
||||
card.save().then(() => {
|
||||
var house = new House();
|
||||
var relation = house.relation('cards');
|
||||
relation.add(card);
|
||||
return house.save();
|
||||
}).then(() => {
|
||||
var query = new Parse.Query('House');
|
||||
query.equalTo('cards', card);
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
62
spec/ParseRole.spec.js
Normal file
62
spec/ParseRole.spec.js
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
// Roles are not accessible without the master key, so they are not intended
|
||||
// for use by clients. We can manually test them using the master key.
|
||||
|
||||
describe('Parse Role testing', () => {
|
||||
|
||||
it('Do a bunch of basic role testing', (done) => {
|
||||
|
||||
var user;
|
||||
var role;
|
||||
|
||||
createTestUser().then((x) => {
|
||||
user = x;
|
||||
role = new Parse.Object('_Role');
|
||||
role.set('name', 'Foos');
|
||||
var users = role.relation('users');
|
||||
users.add(user);
|
||||
return role.save({}, { useMasterKey: true });
|
||||
}).then((x) => {
|
||||
var query = new Parse.Query('_Role');
|
||||
return query.find({ useMasterKey: true });
|
||||
}).then((x) => {
|
||||
expect(x.length).toEqual(1);
|
||||
var relation = x[0].relation('users').query();
|
||||
return relation.first({ useMasterKey: true });
|
||||
}).then((x) => {
|
||||
expect(x.id).toEqual(user.id);
|
||||
// Here we've got a valid role and a user assigned.
|
||||
// Lets create an object only the role can read/write and test
|
||||
// the different scenarios.
|
||||
var obj = new Parse.Object('TestObject');
|
||||
var acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(false);
|
||||
acl.setPublicWriteAccess(false);
|
||||
acl.setRoleReadAccess('Foos', true);
|
||||
acl.setRoleWriteAccess('Foos', true);
|
||||
obj.setACL(acl);
|
||||
return obj.save();
|
||||
}).then((x) => {
|
||||
var query = new Parse.Query('TestObject');
|
||||
return query.find({ sessionToken: user.getSessionToken() });
|
||||
}).then((x) => {
|
||||
expect(x.length).toEqual(1);
|
||||
var objAgain = x[0];
|
||||
objAgain.set('foo', 'bar');
|
||||
// This should succeed:
|
||||
return objAgain.save({}, {sessionToken: user.getSessionToken()});
|
||||
}).then((x) => {
|
||||
x.set('foo', 'baz');
|
||||
// This should fail:
|
||||
return x.save();
|
||||
}).then((x) => {
|
||||
fail('Should not have been able to save.');
|
||||
}, (e) => {
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
1595
spec/ParseUser.spec.js
Normal file
1595
spec/ParseUser.spec.js
Normal file
File diff suppressed because it is too large
Load Diff
128
spec/RestCreate.spec.js
Normal file
128
spec/RestCreate.spec.js
Normal file
@@ -0,0 +1,128 @@
|
||||
// These tests check the "create" functionality of the REST API.
|
||||
var auth = require('../Auth');
|
||||
var cache = require('../cache');
|
||||
var Config = require('../Config');
|
||||
var DatabaseAdapter = require('../DatabaseAdapter');
|
||||
var Parse = require('parse/node').Parse;
|
||||
var rest = require('../rest');
|
||||
var request = require('request');
|
||||
|
||||
var config = new Config('test');
|
||||
var database = DatabaseAdapter.getDatabaseConnection('test');
|
||||
|
||||
describe('rest create', () => {
|
||||
it('handles _id', (done) => {
|
||||
rest.create(config, auth.nobody(config), 'Foo', {}).then(() => {
|
||||
return database.mongoFind('Foo', {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var obj = results[0];
|
||||
expect(typeof obj._id).toEqual('string');
|
||||
expect(obj.objectId).toBeUndefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('handles array, object, date', (done) => {
|
||||
var obj = {
|
||||
array: [1, 2, 3],
|
||||
object: {foo: 'bar'},
|
||||
date: Parse._encode(new Date()),
|
||||
};
|
||||
rest.create(config, auth.nobody(config), 'MyClass', obj).then(() => {
|
||||
return database.mongoFind('MyClass', {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var mob = results[0];
|
||||
expect(mob.array instanceof Array).toBe(true);
|
||||
expect(typeof mob.object).toBe('object');
|
||||
expect(mob.date instanceof Date).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('handles user signup', (done) => {
|
||||
var user = {
|
||||
username: 'asdf',
|
||||
password: 'zxcv',
|
||||
foo: 'bar',
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_User', user)
|
||||
.then((r) => {
|
||||
expect(Object.keys(r.response).length).toEqual(3);
|
||||
expect(typeof r.response.objectId).toEqual('string');
|
||||
expect(typeof r.response.createdAt).toEqual('string');
|
||||
expect(typeof r.response.sessionToken).toEqual('string');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test facebook signup and login', (done) => {
|
||||
var data = {
|
||||
authData: {
|
||||
facebook: {
|
||||
id: '8675309',
|
||||
access_token: 'jenny'
|
||||
}
|
||||
}
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_User', data)
|
||||
.then((r) => {
|
||||
expect(typeof r.response.objectId).toEqual('string');
|
||||
expect(typeof r.response.createdAt).toEqual('string');
|
||||
expect(typeof r.response.sessionToken).toEqual('string');
|
||||
return rest.create(config, auth.nobody(config), '_User', data);
|
||||
}).then((r) => {
|
||||
expect(typeof r.response.objectId).toEqual('string');
|
||||
expect(typeof r.response.createdAt).toEqual('string');
|
||||
expect(typeof r.response.username).toEqual('string');
|
||||
expect(typeof r.response.updatedAt).toEqual('string');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('stores pointers with a _p_ prefix', (done) => {
|
||||
var obj = {
|
||||
foo: 'bar',
|
||||
aPointer: {
|
||||
__type: 'Pointer',
|
||||
className: 'JustThePointer',
|
||||
objectId: 'qwerty'
|
||||
}
|
||||
};
|
||||
rest.create(config, auth.nobody(config), 'APointerDarkly', obj)
|
||||
.then((r) => {
|
||||
return database.mongoFind('APointerDarkly', {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
var output = results[0];
|
||||
expect(typeof output._id).toEqual('string');
|
||||
expect(typeof output._p_aPointer).toEqual('string');
|
||||
expect(output._p_aPointer).toEqual('JustThePointer$qwerty');
|
||||
expect(output.aPointer).toBeUndefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("cannot set objectId", (done) => {
|
||||
var headers = {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
request.post({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/TestObject',
|
||||
body: JSON.stringify({
|
||||
'foo': 'bar',
|
||||
'objectId': 'hello'
|
||||
})
|
||||
}, (error, response, body) => {
|
||||
var b = JSON.parse(body);
|
||||
expect(b.code).toEqual(105);
|
||||
expect(b.error).toEqual('objectId is an invalid field name.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
95
spec/RestQuery.spec.js
Normal file
95
spec/RestQuery.spec.js
Normal file
@@ -0,0 +1,95 @@
|
||||
// These tests check the "find" functionality of the REST API.
|
||||
var auth = require('../Auth');
|
||||
var cache = require('../cache');
|
||||
var Config = require('../Config');
|
||||
var rest = require('../rest');
|
||||
|
||||
var config = new Config('test');
|
||||
var nobody = auth.nobody(config);
|
||||
|
||||
describe('rest query', () => {
|
||||
it('basic query', (done) => {
|
||||
rest.create(config, nobody, 'TestObject', {}).then(() => {
|
||||
return rest.find(config, nobody, 'TestObject', {});
|
||||
}).then((response) => {
|
||||
expect(response.results.length).toEqual(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('query with limit', (done) => {
|
||||
rest.create(config, nobody, 'TestObject', {foo: 'baz'}
|
||||
).then(() => {
|
||||
return rest.create(config, nobody,
|
||||
'TestObject', {foo: 'qux'});
|
||||
}).then(() => {
|
||||
return rest.find(config, nobody,
|
||||
'TestObject', {}, {limit: 1});
|
||||
}).then((response) => {
|
||||
expect(response.results.length).toEqual(1);
|
||||
expect(response.results[0].foo).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// Created to test a scenario in AnyPic
|
||||
it('query with include', (done) => {
|
||||
var photo = {
|
||||
foo: 'bar'
|
||||
};
|
||||
var user = {
|
||||
username: 'aUsername',
|
||||
password: 'aPassword'
|
||||
};
|
||||
var activity = {
|
||||
type: 'comment',
|
||||
photo: {
|
||||
__type: 'Pointer',
|
||||
className: 'TestPhoto',
|
||||
objectId: ''
|
||||
},
|
||||
fromUser: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: ''
|
||||
}
|
||||
};
|
||||
var queryWhere = {
|
||||
photo: {
|
||||
__type: 'Pointer',
|
||||
className: 'TestPhoto',
|
||||
objectId: ''
|
||||
},
|
||||
type: 'comment'
|
||||
};
|
||||
var queryOptions = {
|
||||
include: 'fromUser',
|
||||
order: 'createdAt',
|
||||
limit: 30
|
||||
};
|
||||
rest.create(config, nobody, 'TestPhoto', photo
|
||||
).then((p) => {
|
||||
photo = p;
|
||||
return rest.create(config, nobody, '_User', user);
|
||||
}).then((u) => {
|
||||
user = u.response;
|
||||
activity.photo.objectId = photo.objectId;
|
||||
activity.fromUser.objectId = user.objectId;
|
||||
return rest.create(config, nobody,
|
||||
'TestActivity', activity);
|
||||
}).then(() => {
|
||||
queryWhere.photo.objectId = photo.objectId;
|
||||
return rest.find(config, nobody,
|
||||
'TestActivity', queryWhere, queryOptions);
|
||||
}).then((response) => {
|
||||
var results = response.results;
|
||||
expect(results.length).toEqual(1);
|
||||
expect(typeof results[0].objectId).toEqual('string');
|
||||
expect(typeof results[0].photo).toEqual('object');
|
||||
expect(typeof results[0].fromUser).toEqual('object');
|
||||
expect(typeof results[0].fromUser.username).toEqual('string');
|
||||
done();
|
||||
}).catch((error) => { console.log(error); });
|
||||
});
|
||||
|
||||
});
|
||||
134
spec/Schema.spec.js
Normal file
134
spec/Schema.spec.js
Normal file
@@ -0,0 +1,134 @@
|
||||
// These tests check that the Schema operates correctly.
|
||||
var Config = require('../Config');
|
||||
var Schema = require('../Schema');
|
||||
|
||||
var config = new Config('test');
|
||||
|
||||
describe('Schema', () => {
|
||||
it('can validate one object', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
return schema.validateObject('TestObject', {a: 1, b: 'yo', c: false});
|
||||
}).then((schema) => {
|
||||
done();
|
||||
}, (error) => {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can validate two objects in a row', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
return schema.validateObject('Foo', {x: true, y: 'yyy', z: 0});
|
||||
}).then((schema) => {
|
||||
return schema.validateObject('Foo', {x: false, y: 'YY', z: 1});
|
||||
}).then((schema) => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects inconsistent types', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
return schema.validateObject('Stuff', {bacon: 7});
|
||||
}).then((schema) => {
|
||||
return schema.validateObject('Stuff', {bacon: 'z'});
|
||||
}).then(() => {
|
||||
fail('expected invalidity');
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('updates when new fields are added', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
return schema.validateObject('Stuff', {bacon: 7});
|
||||
}).then((schema) => {
|
||||
return schema.validateObject('Stuff', {sausage: 8});
|
||||
}).then((schema) => {
|
||||
return schema.validateObject('Stuff', {sausage: 'ate'});
|
||||
}).then(() => {
|
||||
fail('expected invalidity');
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('class-level permissions test find', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'find': {}
|
||||
});
|
||||
}).then((schema) => {
|
||||
var query = new Parse.Query('Stuff');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
fail('Class permissions should have rejected this query.');
|
||||
done();
|
||||
}, (e) => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('class-level permissions test user', (done) => {
|
||||
var user;
|
||||
createTestUser().then((u) => {
|
||||
user = u;
|
||||
return config.database.loadSchema();
|
||||
}).then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
var find = {};
|
||||
find[user.id] = true;
|
||||
return schema.setPermissions('Stuff', {
|
||||
'find': find
|
||||
});
|
||||
}).then((schema) => {
|
||||
var query = new Parse.Query('Stuff');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
done();
|
||||
}, (e) => {
|
||||
fail('Class permissions should have allowed this query.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('class-level permissions test get', (done) => {
|
||||
var user;
|
||||
var obj;
|
||||
createTestUser().then((u) => {
|
||||
user = u;
|
||||
return config.database.loadSchema();
|
||||
}).then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
var find = {};
|
||||
var get = {};
|
||||
get[user.id] = true;
|
||||
return schema.setPermissions('Stuff', {
|
||||
'find': find,
|
||||
'get': get
|
||||
});
|
||||
}).then((schema) => {
|
||||
obj = new Parse.Object('Stuff');
|
||||
obj.set('foo', 'bar');
|
||||
return obj.save();
|
||||
}).then((o) => {
|
||||
obj = o;
|
||||
var query = new Parse.Query('Stuff');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
fail('Class permissions should have rejected this query.');
|
||||
done();
|
||||
}, (e) => {
|
||||
var query = new Parse.Query('Stuff');
|
||||
return query.get(obj.id).then((o) => {
|
||||
done();
|
||||
}, (e) => {
|
||||
fail('Class permissions should have allowed this get query');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
217
spec/helper.js
Normal file
217
spec/helper.js
Normal file
@@ -0,0 +1,217 @@
|
||||
// Sets up a Parse API server for testing.
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
|
||||
|
||||
var cache = require('../cache');
|
||||
var DatabaseAdapter = require('../DatabaseAdapter');
|
||||
var express = require('express');
|
||||
var facebook = require('../facebook');
|
||||
var ParseServer = require('../index').ParseServer;
|
||||
|
||||
var databaseURI = process.env.DATABASE_URI;
|
||||
var cloudMain = process.env.CLOUD_CODE_MAIN || './cloud/main.js';
|
||||
|
||||
// Set up an API server for testing
|
||||
var api = new ParseServer({
|
||||
databaseURI: databaseURI,
|
||||
cloud: cloudMain,
|
||||
appId: 'test',
|
||||
javascriptKey: 'test',
|
||||
dotNetKey: 'windows',
|
||||
clientKey: 'client',
|
||||
restAPIKey: 'rest',
|
||||
masterKey: 'test',
|
||||
collectionPrefix: 'test_',
|
||||
fileKey: 'test'
|
||||
});
|
||||
|
||||
var app = express();
|
||||
app.use('/1', api);
|
||||
var port = 8378;
|
||||
var server = app.listen(port);
|
||||
|
||||
// Set up a Parse client to talk to our test API server
|
||||
var Parse = require('parse/node');
|
||||
Parse.serverURL = 'http://localhost:' + port + '/1';
|
||||
|
||||
// This is needed because we ported a bunch of tests from the non-A+ way.
|
||||
// TODO: update tests to work in an A+ way
|
||||
Parse.Promise.disableAPlusCompliant();
|
||||
|
||||
beforeEach(function(done) {
|
||||
Parse.initialize('test', 'test', 'test');
|
||||
mockFacebook();
|
||||
Parse.User.enableUnsafeCurrentUser();
|
||||
done();
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
Parse.User.logOut();
|
||||
Parse.Promise.as().then(() => {
|
||||
return clearData();
|
||||
}).then(() => {
|
||||
done();
|
||||
}, (error) => {
|
||||
console.log('error in clearData', error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
var TestObject = Parse.Object.extend({
|
||||
className: "TestObject"
|
||||
});
|
||||
var Item = Parse.Object.extend({
|
||||
className: "Item"
|
||||
});
|
||||
var Container = Parse.Object.extend({
|
||||
className: "Container"
|
||||
});
|
||||
|
||||
// Convenience method to create a new TestObject with a callback
|
||||
function create(options, callback) {
|
||||
var t = new TestObject(options);
|
||||
t.save(null, { success: callback });
|
||||
}
|
||||
|
||||
function createTestUser(success, error) {
|
||||
var user = new Parse.User();
|
||||
user.set('username', 'test');
|
||||
user.set('password', 'moon-y');
|
||||
var promise = user.signUp();
|
||||
if (success || error) {
|
||||
promise.then(function(user) {
|
||||
if (success) {
|
||||
success(user);
|
||||
}
|
||||
}, function(err) {
|
||||
if (error) {
|
||||
error(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the tests that are known to not work.
|
||||
function notWorking() {}
|
||||
|
||||
// Shims for compatibility with the old qunit tests.
|
||||
function ok(bool, message) {
|
||||
expect(bool).toBeTruthy(message);
|
||||
}
|
||||
function equal(a, b, message) {
|
||||
expect(a).toEqual(b, message);
|
||||
}
|
||||
function strictEqual(a, b, message) {
|
||||
expect(a).toBe(b, message);
|
||||
}
|
||||
function notEqual(a, b, message) {
|
||||
expect(a).not.toEqual(b, message);
|
||||
}
|
||||
function expectSuccess(params) {
|
||||
return {
|
||||
success: params.success,
|
||||
error: function(e) {
|
||||
console.log('got error', e);
|
||||
fail('failure happened in expectSuccess');
|
||||
},
|
||||
}
|
||||
}
|
||||
function expectError(errorCode, callback) {
|
||||
return {
|
||||
success: function(result) {
|
||||
console.log('got result', result);
|
||||
fail('expected error but got success');
|
||||
},
|
||||
error: function(obj, e) {
|
||||
// Some methods provide 2 parameters.
|
||||
e = e || obj;
|
||||
if (!e) {
|
||||
fail('expected a specific error but got a blank error');
|
||||
return;
|
||||
}
|
||||
expect(e.code).toEqual(errorCode, e.message);
|
||||
if (callback) {
|
||||
callback(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Because node doesn't have Parse._.contains
|
||||
function arrayContains(arr, item) {
|
||||
return -1 != arr.indexOf(item);
|
||||
}
|
||||
|
||||
// Normalizes a JSON object.
|
||||
function normalize(obj) {
|
||||
if (typeof obj !== 'object') {
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
if (obj instanceof Array) {
|
||||
return '[' + obj.map(normalize).join(', ') + ']';
|
||||
}
|
||||
var answer = '{';
|
||||
for (key of Object.keys(obj).sort()) {
|
||||
answer += key + ': ';
|
||||
answer += normalize(obj[key]);
|
||||
answer += ', ';
|
||||
}
|
||||
answer += '}';
|
||||
return answer;
|
||||
}
|
||||
|
||||
// Asserts two json structures are equal.
|
||||
function jequal(o1, o2) {
|
||||
expect(normalize(o1)).toEqual(normalize(o2));
|
||||
}
|
||||
|
||||
function range(n) {
|
||||
var answer = [];
|
||||
for (var i = 0; i < n; i++) {
|
||||
answer.push(i);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
function mockFacebook() {
|
||||
facebook.validateUserId = function(userId, accessToken) {
|
||||
if (userId === '8675309' && accessToken === 'jenny') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject();
|
||||
};
|
||||
facebook.validateAppId = function(appId, accessToken) {
|
||||
if (accessToken === 'jenny') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject();
|
||||
};
|
||||
}
|
||||
|
||||
function clearData() {
|
||||
var promises = [];
|
||||
for (conn in DatabaseAdapter.dbConnections) {
|
||||
promises.push(DatabaseAdapter.dbConnections[conn].deleteEverything());
|
||||
}
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
// This is polluting, but, it makes it way easier to directly port old tests.
|
||||
global.Parse = Parse;
|
||||
global.TestObject = TestObject;
|
||||
global.Item = Item;
|
||||
global.Container = Container;
|
||||
global.create = create;
|
||||
global.createTestUser = createTestUser;
|
||||
global.notWorking = notWorking;
|
||||
global.ok = ok;
|
||||
global.equal = equal;
|
||||
global.strictEqual = strictEqual;
|
||||
global.notEqual = notEqual;
|
||||
global.expectSuccess = expectSuccess;
|
||||
global.expectError = expectError;
|
||||
global.arrayContains = arrayContains;
|
||||
global.jequal = jequal;
|
||||
global.range = range;
|
||||
10
spec/support/jasmine.json
Normal file
10
spec/support/jasmine.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"spec_dir": "spec",
|
||||
"spec_files": [
|
||||
"*spec.js"
|
||||
],
|
||||
"helpers": [
|
||||
"helper.js"
|
||||
]
|
||||
}
|
||||
|
||||
154
spec/transform.spec.js
Normal file
154
spec/transform.spec.js
Normal file
@@ -0,0 +1,154 @@
|
||||
// These tests are unit tests designed to only test transform.js.
|
||||
|
||||
var transform = require('../transform');
|
||||
|
||||
var dummyConfig = {
|
||||
schema: {
|
||||
data: {},
|
||||
getExpectedType: function(className, key) {
|
||||
if (key == 'userPointer') {
|
||||
return '*_User';
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
describe('transformCreate', () => {
|
||||
|
||||
it('a basic number', (done) => {
|
||||
var input = {five: 5};
|
||||
var output = transform.transformCreate(dummyConfig, null, input);
|
||||
jequal(input, output);
|
||||
done();
|
||||
});
|
||||
|
||||
it('built-in timestamps', (done) => {
|
||||
var input = {
|
||||
createdAt: "2015-10-06T21:24:50.332Z",
|
||||
updatedAt: "2015-10-06T21:24:50.332Z"
|
||||
};
|
||||
var output = transform.transformCreate(dummyConfig, null, input);
|
||||
expect(output._created_at instanceof Date).toBe(true);
|
||||
expect(output._updated_at instanceof Date).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
it('array of pointers', (done) => {
|
||||
var pointer = {
|
||||
__type: 'Pointer',
|
||||
objectId: 'myId',
|
||||
className: 'Blah',
|
||||
};
|
||||
var out = transform.transformCreate(dummyConfig, null, {pointers: [pointer]});
|
||||
jequal([pointer], out.pointers);
|
||||
done();
|
||||
});
|
||||
|
||||
it('a delete op', (done) => {
|
||||
var input = {deleteMe: {__op: 'Delete'}};
|
||||
var output = transform.transformCreate(dummyConfig, null, input);
|
||||
jequal(output, {});
|
||||
done();
|
||||
});
|
||||
|
||||
it('basic ACL', (done) => {
|
||||
var input = {ACL: {'0123': {'read': true, 'write': true}}};
|
||||
var output = transform.transformCreate(dummyConfig, null, input);
|
||||
// This just checks that it doesn't crash, but it should check format.
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformWhere', () => {
|
||||
it('objectId', (done) => {
|
||||
var out = transform.transformWhere(dummyConfig, null, {objectId: 'foo'});
|
||||
expect(out._id).toEqual('foo');
|
||||
done();
|
||||
});
|
||||
|
||||
it('objectId in a list', (done) => {
|
||||
var input = {
|
||||
objectId: {'$in': ['one', 'two', 'three']},
|
||||
};
|
||||
var output = transform.transformWhere(dummyConfig, null, input);
|
||||
jequal(input.objectId, output._id);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('untransformObject', () => {
|
||||
it('built-in timestamps', (done) => {
|
||||
var input = {createdAt: new Date(), updatedAt: new Date()};
|
||||
var output = transform.untransformObject(dummyConfig, null, input);
|
||||
expect(typeof output.createdAt).toEqual('string');
|
||||
expect(typeof output.updatedAt).toEqual('string');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformKey', () => {
|
||||
it('throws out _password', (done) => {
|
||||
try {
|
||||
transform.transformKey(dummyConfig, '_User', '_password');
|
||||
fail('should have thrown');
|
||||
} catch (e) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('transform schema key changes', () => {
|
||||
|
||||
it('changes new pointer key', (done) => {
|
||||
var input = {
|
||||
somePointer: {__type: 'Pointer', className: 'Micro', objectId: 'oft'}
|
||||
};
|
||||
var output = transform.transformCreate(dummyConfig, null, input);
|
||||
expect(typeof output._p_somePointer).toEqual('string');
|
||||
expect(output._p_somePointer).toEqual('Micro$oft');
|
||||
done();
|
||||
});
|
||||
|
||||
it('changes existing pointer keys', (done) => {
|
||||
var input = {
|
||||
userPointer: {__type: 'Pointer', className: '_User', objectId: 'qwerty'}
|
||||
};
|
||||
var output = transform.transformCreate(dummyConfig, null, input);
|
||||
expect(typeof output._p_userPointer).toEqual('string');
|
||||
expect(output._p_userPointer).toEqual('_User$qwerty');
|
||||
done();
|
||||
});
|
||||
|
||||
it('changes ACL storage to _rperm and _wperm', (done) => {
|
||||
var input = {
|
||||
ACL: {
|
||||
"*": { "read": true },
|
||||
"Kevin": { "write": true }
|
||||
}
|
||||
};
|
||||
var output = transform.transformCreate(dummyConfig, null, input);
|
||||
expect(typeof output._rperm).toEqual('object');
|
||||
expect(typeof output._wperm).toEqual('object');
|
||||
expect(output.ACL).toBeUndefined();
|
||||
expect(output._rperm[0]).toEqual('*');
|
||||
expect(output._wperm[0]).toEqual('Kevin');
|
||||
done();
|
||||
});
|
||||
|
||||
it('untransforms from _rperm and _wperm to ACL', (done) => {
|
||||
var input = {
|
||||
_rperm: ["*"],
|
||||
_wperm: ["Kevin"]
|
||||
};
|
||||
var output = transform.untransformObject(dummyConfig, null, input);
|
||||
expect(typeof output.ACL).toEqual('object');
|
||||
expect(output._rperm).toBeUndefined();
|
||||
expect(output._wperm).toBeUndefined();
|
||||
expect(output.ACL['*']['read']).toEqual(true);
|
||||
expect(output.ACL['Kevin']['write']).toEqual(true);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user