Add and test logic for adding fields to the DB

This commit is contained in:
Drew Gross
2016-02-05 11:21:17 -08:00
parent d934f3a863
commit e6feefd223
3 changed files with 167 additions and 7 deletions

View File

@@ -494,6 +494,7 @@ ExportAdapter.prototype.smartFind = function(coll, where, options) {
var index = {};
index[key] = '2d';
//TODO: condiser moving index creation logic into Schema.js
return coll.createIndex(index).then(() => {
// Retry, but just once.
return coll.find(where, options).toArray();

View File

@@ -137,7 +137,7 @@ function schemaAPITypeToMongoFieldType(type) {
return { error: "invalid JSON", code: Parse.Error.INVALID_JSON };
}
switch (type.type) {
default : return { error: 'invalid field type: ' + type.type };
default: return { error: 'invalid field type: ' + type.type };
case 'Number': return { result: 'number' };
case 'String': return { result: 'string' };
case 'Boolean': return { result: 'boolean' };
@@ -241,14 +241,38 @@ Schema.prototype.addClassIfNotExists = function(className, fields) {
}
}
return this.collection.insertOne({
var mongoObject = {
_id: className,
objectId: 'string',
updatedAt: 'string',
createdAt: 'string',
})
};
for (fieldName in defaultColumns[className]) {
validatedField = schemaAPITypeToMongoFieldType(defaultColumns[className][fieldName]);
if (validatedField.code) {
return Promise.reject(validatedField);
}
mongoObject[fieldName] = validatedField.result;
}
for (fieldName in fields) {
validatedField = schemaAPITypeToMongoFieldType(fields[fieldName]);
if (validatedField.code) {
return Promise.reject(validatedField);
}
mongoObject[fieldName] = validatedField.result;
}
var geoPoints = Object.keys(mongoObject).filter(key => mongoObject[key] === 'geopoint');
if (geoPoints.length > 1) {
return Promise.reject({
code: Parse.Error.INCORRECT_TYPE,
error: 'currently, only one GeoPoint field may exist in an object. Adding ' + geoPoints[1] + ' when ' + geoPoints[0] + ' already exists.',
});
}
return this.collection.insertOne(mongoObject)
.then(result => result.ops[0])
.catch(error => {
if (error.code === 11000) { //Mongo's duplicate key error

View File

@@ -1,6 +1,7 @@
// These tests check that the Schema operates correctly.
var Config = require('../Config');
var Schema = require('../Schema');
var dd = require('deep-diff');
var config = new Config('test');
@@ -142,7 +143,8 @@ describe('Schema', () => {
_id: 'NewClass',
objectId: 'string',
updatedAt: 'string',
createdAt: 'string'
createdAt: 'string',
foo: 'string',
})
done();
});
@@ -183,7 +185,8 @@ describe('Schema', () => {
_id: 'NewClass',
objectId: 'string',
updatedAt: 'string',
createdAt: 'string'
createdAt: 'string',
foo: 'string',
});
});
Promise.all([p1,p2])
@@ -229,4 +232,136 @@ describe('Schema', () => {
done();
});
});
it('refuses to add fields with invalid types', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
foo: {type: 7}
}))
.catch(error => {
expect(error.code).toEqual(Parse.Error.INVALID_JSON);
expect(error.error).toEqual('invalid JSON');
done();
});
});
it('refuses to add fields with invalid pointer types', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
foo: {type: 'Pointer'},
}))
.catch(error => {
expect(error.code).toEqual(135);
expect(error.error).toEqual('type Pointer needs a class name');
done();
});
});
it('refuses to add fields with invalid pointer target', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
foo: {type: 'Pointer', targetClass: 7},
}))
.catch(error => {
expect(error.code).toEqual(Parse.Error.INVALID_JSON);
expect(error.error).toEqual('invalid JSON');
done();
});
});
it('refuses to add fields with invalid Relation type', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
foo: {type: 'Relation', uselessKey: 7},
}))
.catch(error => {
expect(error.code).toEqual(135);
expect(error.error).toEqual('type Relation needs a class name');
done();
});
});
it('refuses to add fields with invalid relation target', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
foo: {type: 'Relation', targetClass: 7},
}))
.catch(error => {
expect(error.code).toEqual(Parse.Error.INVALID_JSON);
expect(error.error).toEqual('invalid JSON');
done();
});
});
it('refuses to add fields with uncreatable pointer target class', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
foo: {type: 'Pointer', targetClass: 'not a valid class name'},
}))
.catch(error => {
expect(error.code).toEqual(Parse.Error.INVALID_CLASS_NAME);
expect(error.error).toEqual('Invalid classname: not a valid class name, classnames can only have alphanumeric characters and _, and must start with an alpha character ');
done();
});
});
it('refuses to add fields with uncreatable relation target class', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
foo: {type: 'Relation', targetClass: 'not a valid class name'},
}))
.catch(error => {
expect(error.code).toEqual(Parse.Error.INVALID_CLASS_NAME);
expect(error.error).toEqual('Invalid classname: not a valid class name, classnames can only have alphanumeric characters and _, and must start with an alpha character ');
done();
});
});
it('will create classes', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
aNumber: {type: 'Number'},
aString: {type: 'String'},
aBool: {type: 'Boolean'},
aDate: {type: 'Date'},
aObject: {type: 'Object'},
aArray: {type: 'Array'},
aGeoPoint: {type: 'GeoPoint'},
aFile: {type: 'File'},
aPointer: {type: 'Pointer', targetClass: 'ThisClassDoesNotExistYet'},
aRelation: {type: 'Relation', targetClass: 'NewClass'},
}))
.then(mongoObj => {
expect(mongoObj).toEqual({
_id: 'NewClass',
objectId: 'string',
createdAt: 'string',
updatedAt: 'string',
aNumber: 'number',
aString: 'string',
aBool: 'boolean',
aDate: 'date',
aObject: 'object',
aArray: 'array',
aGeoPoint: 'geopoint',
aFile: 'file',
aPointer: '*ThisClassDoesNotExistYet',
aRelation: 'relation<NewClass>',
});
done();
});
});
it('refuses to create two geopoints', done => {
config.database.loadSchema()
.then(schema => schema.addClassIfNotExists('NewClass', {
geo1: {type: 'GeoPoint'},
geo2: {type: 'GeoPoint'},
}))
.catch(error => {
expect(error.code).toEqual(Parse.Error.INCORRECT_TYPE);
expect(error.error).toEqual('currently, only one GeoPoint field may exist in an object. Adding geo2 when geo1 already exists.');
done();
});
});
});