Use imperative mood for tests

* Use imperative mood for tests in test/loopback-dl.test.js
This commit is contained in:
Amir Jafarian 2016-10-27 16:36:59 -04:00
parent 9d99f9d2af
commit a65311dc7c
1 changed files with 232 additions and 237 deletions

View File

@ -13,9 +13,9 @@ var jdb = require('../');
var ModelBuilder = jdb.ModelBuilder; var ModelBuilder = jdb.ModelBuilder;
var DataSource = jdb.DataSource; var DataSource = jdb.DataSource;
describe('ModelBuilder define model', function() { describe('ModelBuilder', function() {
it('should be able to define plain models', function(done) { it('supports plain models', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', { var User = modelBuilder.define('User', {
@ -45,7 +45,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should not take unknown properties in strict mode', function(done) { it('ignores unknown properties in strict mode', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', {name: String, bio: String}, {strict: true}); var User = modelBuilder.define('User', {name: String, bio: String}, {strict: true});
@ -62,7 +62,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should ignore non-predefined properties in strict mode', function(done) { it('ignores non-predefined properties in strict mode', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', {name: String, bio: String}, {strict: true}); var User = modelBuilder.define('User', {name: String, bio: String}, {strict: true});
@ -86,7 +86,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should throw when unknown properties are used if strict=throw', function(done) { it('throws an error when unknown properties are used if strict=throw', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', {name: String, bio: String}, {strict: 'throw'}); var User = modelBuilder.define('User', {name: String, bio: String}, {strict: 'throw'});
@ -100,7 +100,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should be able to define open models', function(done) { it('supports open models', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', {}, {strict: false}); var User = modelBuilder.define('User', {}, {strict: false});
@ -115,7 +115,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should take non-predefined properties in non-strict mode', function(done) { it('accepts non-predefined properties in non-strict mode', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', {name: String, bio: String}, {strict: false}); var User = modelBuilder.define('User', {name: String, bio: String}, {strict: false});
@ -140,7 +140,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should use false as the default value for strict', function(done) { it('uses non-strict mode by default', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', {}); var User = modelBuilder.define('User', {});
@ -155,7 +155,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should be able to define nesting models', function(done) { it('supports nested model definitions', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
// simplier way to describe model // simplier way to describe model
@ -217,7 +217,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should be able to reference models by name before they are defined', function(done) { it('allows models to be referenced by name before they are defined', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', {name: String, address: 'Address'}); var User = modelBuilder.define('User', {name: String, address: 'Address'});
@ -249,7 +249,7 @@ describe('ModelBuilder define model', function() {
done(null, User); done(null, User);
}); });
it('should define an id property for composite ids', function() { it('defines an id property for composite ids', function() {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var Follow = modelBuilder.define('Follow', { var Follow = modelBuilder.define('Follow', {
followerId: {type: String, id: 1}, followerId: {type: String, id: 1},
@ -275,7 +275,7 @@ describe('DataSource ping', function() {
cb(new Error('bad connection 2')); cb(new Error('bad connection 2'));
}; };
it('should report connection errors during ping', function(done) { it('reports connection errors during ping', function(done) {
ds.ping(function(err) { ds.ping(function(err) {
(!!err).should.be.true; (!!err).should.be.true;
err.message.should.be.eql('bad connection 2'); err.message.should.be.eql('bad connection 2');
@ -283,7 +283,7 @@ describe('DataSource ping', function() {
}); });
}); });
it('should cancel invocation after timeout', function(done) { it('cancels invocation after timeout', function(done) {
ds.connected = false; // Force connect ds.connected = false; // Force connect
var Post = ds.define('Post', { var Post = ds.define('Post', {
title: {type: String, length: 255}, title: {type: String, length: 255},
@ -297,7 +297,7 @@ describe('DataSource ping', function() {
}); });
describe('DataSource define model', function() { describe('DataSource define model', function() {
it('should be able to define plain models', function() { it('supports plain model definitions', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
// define models // define models
@ -402,7 +402,7 @@ describe('DataSource define model', function() {
}); });
it('should emit events during attach', function() { it('emits events during attach', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
@ -430,7 +430,7 @@ describe('DataSource define model', function() {
assert.equal(dataSourceAttached, 1); assert.equal(dataSourceAttached, 1);
}); });
it('should not take unknown properties in strict mode', function(done) { it('ignores unknown properties in strict mode', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String, bio: String}, {strict: true}); var User = ds.define('User', {name: String, bio: String}, {strict: true});
@ -448,7 +448,7 @@ describe('DataSource define model', function() {
}); });
}); });
it('should throw when unknown properties are used if strict=throw', function(done) { it('throws an error when unknown properties are used if strict=throw', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String, bio: String}, {strict: 'throw'}); var User = ds.define('User', {name: String, bio: String}, {strict: 'throw'});
@ -463,7 +463,7 @@ describe('DataSource define model', function() {
}); });
describe('strict mode "validate"', function() { describe('strict mode "validate"', function() {
it('should report validation error for unknown properties', function() { it('reports validation errors for unknown properties', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String}, {strict: 'validate'}); var User = ds.define('User', {name: String}, {strict: 'validate'});
var user = new User({name: 'Joe', age: 20}); var user = new User({name: 'Joe', age: 20});
@ -473,7 +473,7 @@ describe('DataSource define model', function() {
}); });
}); });
it('should be able to define open models', function(done) { it('supports open model definitions', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {}, {strict: false}); var User = ds.define('User', {}, {strict: false});
@ -496,7 +496,7 @@ describe('DataSource define model', function() {
}); });
}); });
it('should use false as the default value for strict', function(done) { it('uses non-strict mode by default', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {}); var User = ds.define('User', {});
@ -512,7 +512,7 @@ describe('DataSource define model', function() {
}); });
}); });
it('should use true as the default value for strict for relational DBs', function(done) { it('uses strict mode by default for relational DBs', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
ds.connector.relational = true; // HACK ds.connector.relational = true; // HACK
@ -530,7 +530,7 @@ describe('DataSource define model', function() {
done(null, User); done(null, User);
}); });
it('should throw when unknown properties are used if strict=false for relational DBs', function(done) { it('throws an error with unknown properties in non-strict mode for relational DBs', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
ds.connector.relational = true; // HACK ds.connector.relational = true; // HACK
@ -545,7 +545,7 @@ describe('DataSource define model', function() {
done(null, User); done(null, User);
}); });
it('should change the property value for save if strict=false', function(done) { it('changes the property value for save in non-strict mode', function(done) {
var ds = new DataSource('memory');// define models var ds = new DataSource('memory');// define models
var Post = ds.define('Post'); var Post = ds.define('Post');
@ -580,7 +580,7 @@ describe('DataSource define model', function() {
}); });
it('should update the instance with unknown properties', function(done) { it('updates instances with unknown properties in non-strict mode', function(done) {
var ds = new DataSource('memory');// define models var ds = new DataSource('memory');// define models
var Post; var Post;
Post = ds.define('Post', { Post = ds.define('Post', {
@ -641,7 +641,7 @@ describe('DataSource define model', function() {
done(); done();
}); });
it('should allow an explicit remoting path', function() { it('allows an explicit remoting path', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String, bio: String}, { var User = ds.define('User', {name: String, bio: String}, {
@ -650,7 +650,7 @@ describe('DataSource define model', function() {
User.http.path.should.equal('/accounts'); User.http.path.should.equal('/accounts');
}); });
it('should allow an explicit remoting path with leading /', function() { it('allows an explicit remoting path with leading /', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String, bio: String}, { var User = ds.define('User', {name: String, bio: String}, {
@ -661,8 +661,8 @@ describe('DataSource define model', function() {
}); });
describe('Load models with base', function() { describe('Model loaded with a base', function() {
it('should set up base class via base option', function() { it('has a base class according to the base option', function() {
var ds = new ModelBuilder(); var ds = new ModelBuilder();
var User = ds.define('User', {name: String}); var User = ds.define('User', {name: String});
@ -687,7 +687,7 @@ describe('Load models with base', function() {
} }
}); });
it('should inherit properties from base option', function() { it('inherits properties from base model', function() {
var ds = new ModelBuilder(); var ds = new ModelBuilder();
var User = ds.define('User', {name: String}); var User = ds.define('User', {name: String});
@ -698,7 +698,7 @@ describe('Load models with base', function() {
Customer.definition.properties.name.should.have.property('type', String); Customer.definition.properties.name.should.have.property('type', String);
}); });
it('should inherit properties by clone from base option', function() { it('inherits properties by clone from base model', function() {
var ds = new ModelBuilder(); var ds = new ModelBuilder();
var User = ds.define('User', {name: String}); var User = ds.define('User', {name: String});
@ -714,7 +714,7 @@ describe('Load models with base', function() {
Customer2.definition.properties.name); Customer2.definition.properties.name);
}); });
it('should revert properties from base model', function() { it('can remove properties from base model', function() {
var ds = new ModelBuilder(); var ds = new ModelBuilder();
var User = ds.define('User', {username: String, email: String}); var User = ds.define('User', {username: String, email: String});
@ -737,7 +737,7 @@ describe('Load models with base', function() {
u.should.have.property('email', 'x@y.com'); u.should.have.property('email', 'x@y.com');
}); });
it('should set up base class via parent arg', function() { it('can configure base class via parent argument', function() {
var ds = new ModelBuilder(); var ds = new ModelBuilder();
var User = ds.define('User', {name: String}); var User = ds.define('User', {name: String});
@ -775,7 +775,8 @@ describe('Models attached to a dataSource', function() {
Post.destroyAll(done); Post.destroyAll(done);
}); });
it('updateOrCreate should update the instance', function(done) { describe('updateOrCreate', function() {
it('updates instances', function(done) {
Post.create({title: 'a', content: 'AAA'}, function(err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
post.title = 'b'; post.title = 'b';
Post.updateOrCreate(post, function(err, p) { Post.updateOrCreate(post, function(err, p) {
@ -789,15 +790,13 @@ describe('Models attached to a dataSource', function() {
should.not.exist(p._id); should.not.exist(p._id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
p.title.should.be.equal('b'); p.title.should.be.equal('b');
done(); done();
}); });
}); });
}); });
}); });
it('updateOrCreate should update the instance without removing existing properties', function(done) { it('updates instances without removing existing properties', function(done) {
Post.create({title: 'a', content: 'AAA', comments: ['Comment1']}, function(err, post) { Post.create({title: 'a', content: 'AAA', comments: ['Comment1']}, function(err, post) {
post = post.toObject(); post = post.toObject();
delete post.title; delete post.title;
@ -818,11 +817,10 @@ describe('Models attached to a dataSource', function() {
done(); done();
}); });
}); });
}); });
}); });
it('updateOrCreate should create a new instance if it does not exist', function(done) { it('creates a new instance if it does not exist', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'}; var post = {id: 123, title: 'a', content: 'AAA'};
Post.updateOrCreate(post, function(err, p) { Post.updateOrCreate(post, function(err, p) {
should.not.exist(err); should.not.exist(err);
@ -836,14 +834,14 @@ describe('Models attached to a dataSource', function() {
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
p.title.should.be.equal(post.title); p.title.should.be.equal(post.title);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
done(); done();
}); });
}); });
});
}); });
it('save should update the instance with the same id', function(done) { describe('save', function() {
it('updates instance with the same id', function(done) {
Post.create({title: 'a', content: 'AAA'}, function(err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
post.title = 'b'; post.title = 'b';
post.save(function(err, p) { post.save(function(err, p) {
@ -857,7 +855,6 @@ describe('Models attached to a dataSource', function() {
should.not.exist(p._id); should.not.exist(p._id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
p.title.should.be.equal('b'); p.title.should.be.equal('b');
done(); done();
}); });
}); });
@ -865,7 +862,7 @@ describe('Models attached to a dataSource', function() {
}); });
}); });
it('save should update the instance without removing existing properties', function(done) { it('updates the instance without removing existing properties', function(done) {
Post.create({title: 'a', content: 'AAA'}, function(err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
delete post.title; delete post.title;
post.save(function(err, p) { post.save(function(err, p) {
@ -879,15 +876,13 @@ describe('Models attached to a dataSource', function() {
should.not.exist(p._id); should.not.exist(p._id);
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
p.title.should.be.equal('a'); p.title.should.be.equal('a');
done(); done();
}); });
}); });
}); });
}); });
it('save should create a new instance if it does not exist', function(done) { it('creates a new instance if it does not exist', function(done) {
var post = new Post({id: '123', title: 'a', content: 'AAA'}); var post = new Post({id: '123', title: 'a', content: 'AAA'});
post.save(post, function(err, p) { post.save(post, function(err, p) {
should.not.exist(err); should.not.exist(err);
@ -901,40 +896,40 @@ describe('Models attached to a dataSource', function() {
p.content.should.be.equal(post.content); p.content.should.be.equal(post.content);
p.title.should.be.equal(post.title); p.title.should.be.equal(post.title);
p.id.should.be.equal(post.id); p.id.should.be.equal(post.id);
done(); done();
}); });
}); });
});
}); });
}); });
describe('DataSource connector types', function() { describe('DataSource connector types', function() {
it('should return an array of types', function() { it('returns an array of types using getTypes', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var types = ds.getTypes(); var types = ds.getTypes();
assert.deepEqual(types, ['db', 'nosql', 'memory']); assert.deepEqual(types, ['db', 'nosql', 'memory']);
}); });
it('should test supported types by string', function() { describe('supportTypes', function() {
it('tests supported types by string', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var result = ds.supportTypes('db'); var result = ds.supportTypes('db');
assert(result); assert(result);
}); });
it('should test supported types by array', function() { it('tests supported types by array', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var result = ds.supportTypes(['db', 'memory']); var result = ds.supportTypes(['db', 'memory']);
assert(result); assert(result);
}); });
it('should test unsupported types by string', function() { it('tests unsupported types by string', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var result = ds.supportTypes('rdbms'); var result = ds.supportTypes('rdbms');
assert(!result); assert(!result);
}); });
it('should test unsupported types by array', function() { it('tests unsupported types by array', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var result = ds.supportTypes(['rdbms', 'memory']); var result = ds.supportTypes(['rdbms', 'memory']);
assert(!result); assert(!result);
@ -942,7 +937,7 @@ describe('DataSource connector types', function() {
result = ds.supportTypes(['rdbms']); result = ds.supportTypes(['rdbms']);
assert(!result); assert(!result);
}); });
});
}); });
describe('DataSource constructor', function() { describe('DataSource constructor', function() {
@ -961,56 +956,56 @@ describe('DataSource constructor', function() {
}; };
}; };
it('should resolve connector by path', function() { it('resolves connector by path', function() {
var connector = DataSource._resolveConnector(__dirname + '/../lib/connectors/memory'); var connector = DataSource._resolveConnector(__dirname + '/../lib/connectors/memory');
assert(connector.connector); assert(connector.connector);
}); });
it('should resolve connector by internal name', function() { it('resolves connector by internal name', function() {
var connector = DataSource._resolveConnector('memory'); var connector = DataSource._resolveConnector('memory');
assert(connector.connector); assert(connector.connector);
}); });
it('should try to resolve connector by module name starts with loopback-connector-', function() { it('resolves connector by module name starting with loopback-connector-', function() {
var connector = DataSource._resolveConnector('loopback-connector-xyz', loader); var connector = DataSource._resolveConnector('loopback-connector-xyz', loader);
assert(connector.connector); assert(connector.connector);
}); });
it('should try to resolve connector by short module name with full name first', function() { it('resolves connector by short module name with full name first', function() {
var connector = DataSource._resolveConnector('xyz', loader); var connector = DataSource._resolveConnector('xyz', loader);
assert(connector.connector); assert(connector.connector);
assert.equal(connector.connector.name, 'loopback-connector-xyz'); assert.equal(connector.connector.name, 'loopback-connector-xyz');
}); });
it('should try to resolve connector by short module name', function() { it('resolves connector by short module name', function() {
var connector = DataSource._resolveConnector('abc', loader); var connector = DataSource._resolveConnector('abc', loader);
assert(connector.connector); assert(connector.connector);
assert.equal(connector.connector.name, 'abc'); assert.equal(connector.connector.name, 'abc');
}); });
it('should try to resolve connector by short module name for known connectors', function() { it('resolves connector by short module name for known connectors', function() {
var connector = DataSource._resolveConnector('oracle', loader); var connector = DataSource._resolveConnector('oracle', loader);
assert(connector.connector); assert(connector.connector);
assert.equal(connector.connector.name, 'loopback-connector-oracle'); assert.equal(connector.connector.name, 'loopback-connector-oracle');
}); });
it('should try to resolve connector by full module name', function() { it('resolves connector by full module name', function() {
var connector = DataSource._resolveConnector('loopback-xyz', loader); var connector = DataSource._resolveConnector('loopback-xyz', loader);
assert(connector.connector); assert(connector.connector);
}); });
it('should fail to resolve connector by module name starts with loopback-connector-', function() { it('fails to resolve connector by module name starting with loopback-connector-', function() {
var connector = DataSource._resolveConnector('loopback-connector-xyz'); var connector = DataSource._resolveConnector('loopback-connector-xyz');
assert(!connector.connector); assert(!connector.connector);
assert(connector.error.indexOf('loopback-connector-xyz') !== -1); assert(connector.error.indexOf('loopback-connector-xyz') !== -1);
}); });
it('should fail to resolve connector by short module name', function() { it('fails resolve invalid connector by short module name', function() {
var connector = DataSource._resolveConnector('xyz'); var connector = DataSource._resolveConnector('xyz');
assert(!connector.connector); assert(!connector.connector);
assert(connector.error.indexOf('loopback-connector-xyz') !== -1); assert(connector.error.indexOf('loopback-connector-xyz') !== -1);
}); });
it('should fail to resolve connector by full module name', function() { it('fails to resolve invalid connector by full module name', function() {
var connector = DataSource._resolveConnector('loopback-xyz'); var connector = DataSource._resolveConnector('loopback-xyz');
assert(!connector.connector); assert(!connector.connector);
assert(connector.error.indexOf('loopback-connector-loopback-xyz') !== -1); assert(connector.error.indexOf('loopback-connector-loopback-xyz') !== -1);
}); });
}); });
describe('Load models with relations', function() { describe('Model define with relations configuration', function() {
it('should set up relations', function(done) { it('sets up hasMany relations', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Post = ds.define('Post', {userId: Number, content: String}); var Post = ds.define('Post', {userId: Number, content: String});
@ -1022,7 +1017,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should set up belongsTo relations', function(done) { it('sets up belongsTo relations', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String}); var User = ds.define('User', {name: String});
@ -1034,7 +1029,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should set up referencesMany relations', function(done) { it('sets up referencesMany relations', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Post = ds.define('Post', {userId: Number, content: String}); var Post = ds.define('Post', {userId: Number, content: String});
@ -1046,7 +1041,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should set up embedsMany relations', function(done) { it('sets up embedsMany relations', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Post = ds.define('Post', {userId: Number, content: String}); var Post = ds.define('Post', {userId: Number, content: String});
@ -1058,7 +1053,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should set up polymorphic relations', function(done) { it('sets up polymorphic relations', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Author = ds.define('Author', {name: String}, {relations: { var Author = ds.define('Author', {name: String}, {relations: {
@ -1102,7 +1097,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should set up foreign key with the correct type', function(done) { it('creates a foreign key with the correct type', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String, id: {type: String, id: true}}); var User = ds.define('User', {name: String, id: {type: String, id: true}});
@ -1117,7 +1112,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should set up hasMany and belongsTo relations', function(done) { it('sets up related hasMany and belongsTo relations', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String}, { var User = ds.define('User', {name: String}, {
@ -1172,7 +1167,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should throw if a relation is missing type', function(done) { it('throws an error if a relation is missing type', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Post = ds.define('Post', {userId: Number, content: String}); var Post = ds.define('Post', {userId: Number, content: String});
@ -1187,7 +1182,7 @@ describe('Load models with relations', function() {
}); });
it('should throw if the relation type is invalid', function(done) { it('throws an error if a relation type is invalid', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Post = ds.define('Post', {userId: Number, content: String}); var Post = ds.define('Post', {userId: Number, content: String});
@ -1202,7 +1197,7 @@ describe('Load models with relations', function() {
}); });
it('should handle hasMany through', function(done) { it('sets up hasMany through relations', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Physician = ds.createModel('Physician', { var Physician = ds.createModel('Physician', {
name: String, name: String,
@ -1239,7 +1234,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should handle hasMany through options', function(done) { it('sets up hasMany through relations with options', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var Physician = ds.createModel('Physician', { var Physician = ds.createModel('Physician', {
name: String, name: String,
@ -1273,7 +1268,7 @@ describe('Load models with relations', function() {
done(); done();
}); });
it('should set up relations after attach', function(done) { it('sets up relations after attach', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
@ -1291,8 +1286,8 @@ describe('Load models with relations', function() {
}); });
describe('Model with scopes', function() { describe('Model define with scopes configuration', function() {
it('should create scopes', function(done) { it('creates scopes', function(done) {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var User = ds.define('User', {name: String, vip: Boolean, age: Number}, var User = ds.define('User', {name: String, vip: Boolean, age: Number},
{scopes: {vips: {where: {vip: true}}, top5: {limit: 5, order: 'age'}}}); {scopes: {vips: {where: {vip: true}}, top5: {limit: 5, order: 'age'}}});
@ -1337,7 +1332,7 @@ describe('DataAccessObject', function() {
error = null; error = null;
}); });
it('should be able to coerce where clause for string types', function() { it('coerces where clause for string types', function() {
where = model._coerce({id: 1}); where = model._coerce({id: 1});
assert.deepEqual(where, {id: '1'}); assert.deepEqual(where, {id: '1'});
where = model._coerce({id: '1'}); where = model._coerce({id: '1'});
@ -1356,7 +1351,7 @@ describe('DataAccessObject', function() {
assert.deepEqual(where, {id: '1'}); assert.deepEqual(where, {id: '1'});
}); });
it('should be able to coerce where clause for number types', function() { it('coerces where clause for number types', function() {
where = model._coerce({age: '10'}); where = model._coerce({age: '10'});
assert.deepEqual(where, {age: 10}); assert.deepEqual(where, {age: 10});
@ -1373,12 +1368,12 @@ describe('DataAccessObject', function() {
assert.deepEqual(where, {age: {between: [10, 20]}}); assert.deepEqual(where, {age: {between: [10, 20]}});
}); });
it('should be able to coerce where clause for array types', function() { it('coerces where clause for array types', function() {
where = model._coerce({scores: ['10', '20']}); where = model._coerce({scores: ['10', '20']});
assert.deepEqual(where, {scores: [10, 20]}); assert.deepEqual(where, {scores: [10, 20]});
}); });
it('should be able to coerce where clause for date types', function() { it('coerces where clause for date types', function() {
var d = new Date(); var d = new Date();
where = model._coerce({date: d}); where = model._coerce({date: d});
assert.deepEqual(where, {date: d}); assert.deepEqual(where, {date: d});
@ -1387,7 +1382,7 @@ describe('DataAccessObject', function() {
assert.deepEqual(where, {date: d}); assert.deepEqual(where, {date: d});
}); });
it('should be able to coerce where clause for boolean types', function() { it('coerces where clause for boolean types', function() {
where = model._coerce({vip: 'true'}); where = model._coerce({vip: 'true'});
assert.deepEqual(where, {vip: true}); assert.deepEqual(where, {vip: true});
@ -1411,12 +1406,12 @@ describe('DataAccessObject', function() {
}); });
it('should be able to coerce where clause with and operators', function() { it('coerces where clause with and operators', function() {
where = model._coerce({and: [{age: '10'}, {vip: 'true'}]}); where = model._coerce({and: [{age: '10'}, {vip: 'true'}]});
assert.deepEqual(where, {and: [{age: 10}, {vip: true}]}); assert.deepEqual(where, {and: [{age: 10}, {vip: true}]});
}); });
it('should be able to coerce where clause with or operators', function() { it('coerces where clause with or operators', function() {
where = model._coerce({or: [{age: '10'}, {vip: 'true'}]}); where = model._coerce({or: [{age: '10'}, {vip: 'true'}]});
assert.deepEqual(where, {or: [{age: 10}, {vip: true}]}); assert.deepEqual(where, {or: [{age: 10}, {vip: true}]});
}); });
@ -1431,7 +1426,7 @@ describe('DataAccessObject', function() {
assert.deepEqual(where, {and: [{age: 10}], vip: true}); assert.deepEqual(where, {and: [{age: 10}], vip: true});
}); });
it('should throw if the where property is not an object', function() { it('throws an error if the where property is not an object', function() {
try { try {
// The where clause has to be an object // The where clause has to be an object
model._coerce('abc'); model._coerce('abc');
@ -1441,7 +1436,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if the where property is an array', function() { it('throws an error if the where property is an array', function() {
try { try {
// The where clause cannot be an array // The where clause cannot be an array
model._coerce([ model._coerce([
@ -1453,7 +1448,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if the and operator does not take an array', function() { it('throws an error if the and operator is not configured with an array', function() {
try { try {
// The and operator only takes an array of objects // The and operator only takes an array of objects
model._coerce({and: {x: 1}}); model._coerce({and: {x: 1}});
@ -1463,7 +1458,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if the or operator does not take an array', function() { it('throws an error if the or operator does not take an array', function() {
try { try {
// The or operator only takes an array of objects // The or operator only takes an array of objects
model._coerce({or: {x: 1}}); model._coerce({or: {x: 1}});
@ -1473,7 +1468,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if the or operator does not take an array of objects', function() { it('throws an error if the or operator not configured with an array of objects', function() {
try { try {
// The or operator only takes an array of objects // The or operator only takes an array of objects
model._coerce({or: ['x']}); model._coerce({or: ['x']});
@ -1497,7 +1492,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if filter property is not an object', function() { it('throws an error if the filter property is not an object', function() {
var filter = null; var filter = null;
try { try {
// The filter clause has to be an object // The filter clause has to be an object
@ -1508,7 +1503,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if filter.limit property is not a number', function() { it('throws an error if the filter.limit property is not a number', function() {
try { try {
// The limit param must be a valid number // The limit param must be a valid number
filter = model._normalize({limit: 'x'}); filter = model._normalize({limit: 'x'});
@ -1518,7 +1513,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if filter.limit property is nagative', function() { it('throws an error if the filter.limit property is nagative', function() {
try { try {
// The limit param must be a valid number // The limit param must be a valid number
filter = model._normalize({limit: -1}); filter = model._normalize({limit: -1});
@ -1528,7 +1523,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if filter.limit property is not an integer', function() { it('throws an error if the filter.limit property is not an integer', function() {
try { try {
// The limit param must be a valid number // The limit param must be a valid number
filter = model._normalize({limit: 5.8}); filter = model._normalize({limit: 5.8});
@ -1538,7 +1533,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if filter.offset property is not a number', function() { it('throws an error if filter.offset property is not a number', function() {
try { try {
// The limit param must be a valid number // The limit param must be a valid number
filter = model._normalize({offset: 'x'}); filter = model._normalize({offset: 'x'});
@ -1548,7 +1543,7 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should throw if filter.skip property is not a number', function() { it('throws an error if the filter.skip property is not a number', function() {
try { try {
// The limit param must be a valid number // The limit param must be a valid number
filter = model._normalize({skip: '_'}); filter = model._normalize({skip: '_'});
@ -1558,17 +1553,17 @@ describe('DataAccessObject', function() {
assert(error, 'An error should have been thrown'); assert(error, 'An error should have been thrown');
}); });
it('should normalize limit/offset/skip', function() { it('normalizes limit/offset/skip', function() {
filter = model._normalize({limit: '10', skip: 5}); filter = model._normalize({limit: '10', skip: 5});
assert.deepEqual(filter, {limit: 10, offset: 5, skip: 5}); assert.deepEqual(filter, {limit: 10, offset: 5, skip: 5});
}); });
it('should set the default value for limit', function() { it('uses a default value for limit', function() {
filter = model._normalize({skip: 5}); filter = model._normalize({skip: 5});
assert.deepEqual(filter, {limit: 100, offset: 5, skip: 5}); assert.deepEqual(filter, {limit: 100, offset: 5, skip: 5});
}); });
it('should apply settings for handling undefined', function() { it('applies settings for handling undefined', function() {
filter = model._normalize({filter: {x: undefined}}); filter = model._normalize({filter: {x: undefined}});
assert.deepEqual(filter, {filter: {}}); assert.deepEqual(filter, {filter: {}});
@ -1584,35 +1579,35 @@ describe('DataAccessObject', function() {
(function() { model._normalize({filter: {x: undefined}}); }).should.throw(/`undefined` in query/); (function() { model._normalize({filter: {x: undefined}}); }).should.throw(/`undefined` in query/);
}); });
it('should skip GeoPoint', function() { it('does not coerce GeoPoint', function() {
where = model._coerce({location: {near: {lng: 10, lat: 20}, maxDistance: 20}}); where = model._coerce({location: {near: {lng: 10, lat: 20}, maxDistance: 20}});
assert.deepEqual(where, {location: {near: {lng: 10, lat: 20}, maxDistance: 20}}); assert.deepEqual(where, {location: {near: {lng: 10, lat: 20}, maxDistance: 20}});
}); });
it('should skip null values', function() { it('does not coerce null values', function() {
where = model._coerce({date: null}); where = model._coerce({date: null});
assert.deepEqual(where, {date: null}); assert.deepEqual(where, {date: null});
}); });
it('should skip undefined values', function() { it('does not coerce undefined values', function() {
where = model._coerce({date: undefined}); where = model._coerce({date: undefined});
assert.deepEqual(where, {date: undefined}); assert.deepEqual(where, {date: undefined});
}); });
it('should skip conversion if a simple property produces NaN for numbers', it('does not coerce to a number for a simple value that produces NaN',
function() { function() {
where = model._coerce({age: 'xyz'}); where = model._coerce({age: 'xyz'});
assert.deepEqual(where, {age: 'xyz'}); assert.deepEqual(where, {age: 'xyz'});
}); });
it('should skip conversion if an array property produces NaN for numbers', it('does not coerce to a number for a simple value in an array that produces NaN',
function() { function() {
where = model._coerce({age: {inq: ['xyz', '12']}}); where = model._coerce({age: {inq: ['xyz', '12']}});
assert.deepEqual(where, {age: {inq: ['xyz', 12]}}); assert.deepEqual(where, {age: {inq: ['xyz', 12]}});
}); });
// settings // settings
it('should get settings in priority', it('gets settings in priority',
function() { function() {
ds.settings.test = 'test'; ds.settings.test = 'test';
assert.equal(model._getSetting('test'), ds.settings.test, 'Should get datasource setting'); assert.equal(model._getSetting('test'), ds.settings.test, 'Should get datasource setting');
@ -1627,7 +1622,7 @@ describe('DataAccessObject', function() {
}); });
describe('Load models from json', function() { describe('ModelBuilder processing json files', function() {
var path = require('path'), var path = require('path'),
fs = require('fs'); fs = require('fs');
@ -1651,7 +1646,7 @@ describe('Load models from json', function() {
return modelBuilder.buildModels(schemas, createModel); return modelBuilder.buildModels(schemas, createModel);
} }
it('should be able to define models from json', function() { it('defines models', function() {
var models = loadSchemasSync(path.join(__dirname, 'test1-schemas.json')); var models = loadSchemasSync(path.join(__dirname, 'test1-schemas.json'));
@ -1672,7 +1667,7 @@ describe('Load models from json', function() {
} }
}); });
it('should be able to define models from json using dataSource', function() { it('attaches models to a specified dataSource', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var models = loadSchemasSync(path.join(__dirname, 'test2-schemas.json'), ds); var models = loadSchemasSync(path.join(__dirname, 'test2-schemas.json'), ds);
@ -1682,7 +1677,7 @@ describe('Load models from json', function() {
assert.equal(models.Address.dataSource, ds); assert.equal(models.Address.dataSource, ds);
}); });
it('should allow customization of default model base class', function() { it('allows customization of default model base class', function() {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', { var User = modelBuilder.define('User', {
@ -1699,7 +1694,7 @@ describe('Load models from json', function() {
assert(Customer.prototype instanceof User); assert(Customer.prototype instanceof User);
}); });
it('should allow model base class', function() { it('accepts a model base class', function() {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', { var User = modelBuilder.define('User', {
@ -1715,7 +1710,7 @@ describe('Load models from json', function() {
assert(Customer.prototype instanceof User); assert(Customer.prototype instanceof User);
}); });
it('should be able to extend models', function(done) { it('allows model extension', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', { var User = modelBuilder.define('User', {
@ -1759,7 +1754,7 @@ describe('Load models from json', function() {
done(null, customer); done(null, customer);
}); });
it('should be able to extend models with merged settings', function(done) { it('allows model extension with merged settings', function(done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = modelBuilder.define('User', { var User = modelBuilder.define('User', {
@ -1852,29 +1847,29 @@ describe('Load models from json', function() {
}); });
describe('DataSource constructor', function() { describe('DataSource constructor', function() {
it('Takes url as the settings', function() { it('takes url as the settings', function() {
var ds = new DataSource('memory://localhost/mydb?x=1'); var ds = new DataSource('memory://localhost/mydb?x=1');
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
it('Takes connector name', function() { it('takes connector name', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
it('Takes settings object', function() { it('takes settings object', function() {
var ds = new DataSource({connector: 'memory'}); var ds = new DataSource({connector: 'memory'});
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
it('Takes settings object and name', function() { it('takes settings object and name', function() {
var ds = new DataSource('x', {connector: 'memory'}); var ds = new DataSource('x', {connector: 'memory'});
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
}); });
describe('ModelBuilder options.models', function() { describe('ModelBuilder options.models', function() {
it('should inject model classes from models', function() { it('injects model classes from models', function() {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var M1 = builder.define('M1'); var M1 = builder.define('M1');
var M2 = builder.define('M2', {}, {models: { var M2 = builder.define('M2', {}, {models: {
@ -1884,7 +1879,7 @@ describe('ModelBuilder options.models', function() {
assert.equal(M2.M1, M1, 'M1 should be injected to M2'); assert.equal(M2.M1, M1, 'M1 should be injected to M2');
}); });
it('should inject model classes by name in the models', function() { it('injects model classes by name in the models', function() {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var M1 = builder.define('M1'); var M1 = builder.define('M1');
var M2 = builder.define('M2', {}, {models: { var M2 = builder.define('M2', {}, {models: {
@ -1894,7 +1889,7 @@ describe('ModelBuilder options.models', function() {
assert.equal(M2.M1, M1, 'M1 should be injected to M2'); assert.equal(M2.M1, M1, 'M1 should be injected to M2');
}); });
it('should inject model classes by name in the models before the class is defined', it('injects model classes by name in the models before the class is defined',
function() { function() {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var M2 = builder.define('M2', {}, {models: { var M2 = builder.define('M2', {}, {models: {
@ -1906,7 +1901,7 @@ describe('ModelBuilder options.models', function() {
assert.equal(M2.M1, M1, 'M1 should be injected to M2'); assert.equal(M2.M1, M1, 'M1 should be injected to M2');
}); });
it('should use false strict mode for embedded models by default', function() { it('uses non-strict mode for embedded models by default', function() {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var M1 = builder.define('testEmbedded', { var M1 = builder.define('testEmbedded', {
name: 'string', name: 'string',
@ -1924,7 +1919,7 @@ describe('ModelBuilder options.models', function() {
assert.equal(m1.address.number, 5512, 'm1 should contain number property in address'); assert.equal(m1.address.number, 5512, 'm1 should contain number property in address');
}); });
it('should use the strictEmbeddedModels setting (true) when applied on modelBuilder', function() { it('uses the strictEmbeddedModels setting (true) when applied on modelBuilder', function() {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
builder.settings.strictEmbeddedModels = true; builder.settings.strictEmbeddedModels = true;
var M1 = builder.define('testEmbedded', { var M1 = builder.define('testEmbedded', {