Merge pull request #1062 from strongloop/update_eslint

Update eslint
This commit is contained in:
Amirali Jafarian 2016-08-24 15:55:08 -04:00 committed by GitHub
commit fc9b9806c8
83 changed files with 2548 additions and 2426 deletions

View File

@ -8,6 +8,8 @@
}], }],
// NOTE(bajtos) we should eventually remove this override // NOTE(bajtos) we should eventually remove this override
// and fix all of those 100+ violations // and fix all of those 100+ violations
"one-var": "off" "one-var": "off",
"no-unused-expressions": "off",
"strict": ["warn", "global"]
} }
} }

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var DataSource = require('../../loopback-datasource-juggler').DataSource; var DataSource = require('../../loopback-datasource-juggler').DataSource;
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder; var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var introspectType = require('../lib/introspection')(ModelBuilder); var introspectType = require('../lib/introspection')(ModelBuilder);
@ -10,14 +12,14 @@ var introspectType = require('../lib/introspection')(ModelBuilder);
var ds = new DataSource('memory'); var ds = new DataSource('memory');
// Create a open model that doesn't require a schema // Create a open model that doesn't require a schema
var Application = ds.createModel('Schemaless', {}, { strict: false }); var Application = ds.createModel('Schemaless', {}, {strict: false});
var application = { var application = {
owner: 'rfeng', owner: 'rfeng',
name: 'MyApp1', name: 'MyApp1',
description: 'My first app', description: 'My first app',
pushSettings: [ pushSettings: [
{ 'platform': 'apns', {'platform': 'apns',
'apns': { 'apns': {
'pushOptions': { 'pushOptions': {
'gateway': 'gateway.sandbox.push.apple.com', 'gateway': 'gateway.sandbox.push.apple.com',
@ -33,7 +35,7 @@ var application = {
'interval': 300, 'interval': 300,
}, },
}}, }},
] }; ]};
console.log(new Application(application).toObject()); console.log(new Application(application).toObject());
@ -59,8 +61,8 @@ var user = {
}, },
friends: ['John', 'Mary'], friends: ['John', 'Mary'],
emails: [ emails: [
{ label: 'work', id: 'x@sample.com' }, {label: 'work', id: 'x@sample.com'},
{ label: 'home', id: 'x@home.com' }, {label: 'home', id: 'x@home.com'},
], ],
tags: [], tags: [],
}; };
@ -69,7 +71,7 @@ var user = {
var schema = introspectType(user); var schema = introspectType(user);
// Create a model for the generated schema // Create a model for the generated schema
var User = ds.createModel('User', schema, { idInjection: true }); var User = ds.createModel('User', schema, {idInjection: true});
// Use the model for CRUD // Use the model for CRUD
var obj = new User(user); var obj = new User(user);

View File

@ -3,17 +3,19 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder; var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
// define models // define models
var Post = modelBuilder.define('Post', { var Post = modelBuilder.define('Post', {
title: { type: String, length: 255 }, title: {type: String, length: 255},
content: { type: ModelBuilder.Text }, content: {type: ModelBuilder.Text},
date: { type: Date, default: function() { date: {type: Date, default: function() {
return new Date(); return new Date();
} }, }},
timestamp: { type: Number, default: Date.now }, timestamp: {type: Number, default: Date.now},
published: { type: Boolean, default: false, index: true }, published: {type: Boolean, default: false, index: true},
}); });
// simpler way to describe model // simpler way to describe model
@ -25,19 +27,19 @@ var User = modelBuilder.define('User', {
age: Number, age: Number,
}); });
var Group = modelBuilder.define('Group', { group: String }); var Group = modelBuilder.define('Group', {group: String});
// define any custom method // define any custom method
User.prototype.getNameAndAge = function() { User.prototype.getNameAndAge = function() {
return this.name + ', ' + this.age; return this.name + ', ' + this.age;
}; };
var user = new User({ name: 'Joe' }); var user = new User({name: 'Joe'});
console.log(user); console.log(user);
console.log(modelBuilder.models); console.log(modelBuilder.models);
console.log(modelBuilder.definitions); console.log(modelBuilder.definitions);
User.mixin(Group); User.mixin(Group);
var user = new User({ name: 'Ray', group: 'Admin' }); var user = new User({name: 'Ray', group: 'Admin'});
console.log(user); console.log(user);

View File

@ -3,19 +3,21 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var DataSource = require('../../loopback-datasource-juggler').DataSource; var DataSource = require('../../loopback-datasource-juggler').DataSource;
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder; var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var ds = new DataSource('memory'); var ds = new DataSource('memory');
// define models // define models
var Post = ds.define('Post', { var Post = ds.define('Post', {
title: { type: String, length: 255 }, title: {type: String, length: 255},
content: { type: DataSource.Text }, content: {type: DataSource.Text},
date: { type: Date, default: function() { date: {type: Date, default: function() {
return new Date; return new Date;
} }, }},
timestamp: { type: Number, default: Date.now }, timestamp: {type: Number, default: Date.now},
published: { type: Boolean, default: false, index: true }, published: {type: Boolean, default: false, index: true},
}); });
// simplier way to describe model // simplier way to describe model
@ -27,28 +29,28 @@ var User = ds.define('User', {
age: Number, age: Number,
}); });
var Group = ds.define('Group', { name: String }); var Group = ds.define('Group', {name: String});
// define any custom method // define any custom method
User.prototype.getNameAndAge = function() { User.prototype.getNameAndAge = function() {
return this.name + ', ' + this.age; return this.name + ', ' + this.age;
}; };
var user = new User({ name: 'Joe' }); var user = new User({name: 'Joe'});
console.log(user); console.log(user);
// console.log(ds.models); // console.log(ds.models);
// console.log(ds.definitions); // console.log(ds.definitions);
// setup relationships // setup relationships
User.hasMany(Post, { as: 'posts', foreignKey: 'userId' }); User.hasMany(Post, {as: 'posts', foreignKey: 'userId'});
// creates instance methods: // creates instance methods:
// user.posts(conds) // user.posts(conds)
// user.posts.build(data) // like new Post({userId: user.id}); // user.posts.build(data) // like new Post({userId: user.id});
// user.posts.create(data) // build and save // user.posts.create(data) // build and save
Post.belongsTo(User, { as: 'author', foreignKey: 'userId' }); Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
// creates instance methods: // creates instance methods:
// post.author(callback) -- getter when called with function // post.author(callback) -- getter when called with function
// post.author() -- sync getter when called without params // post.author() -- sync getter when called without params
@ -56,44 +58,44 @@ Post.belongsTo(User, { as: 'author', foreignKey: 'userId' });
User.hasAndBelongsToMany('groups'); User.hasAndBelongsToMany('groups');
var user2 = new User({ name: 'Smith', age: 14 }); var user2 = new User({name: 'Smith', age: 14});
user2.save(function(err) { user2.save(function(err) {
console.log(user2); console.log(user2);
var post = user2.posts.build({ title: 'Hello world' }); var post = user2.posts.build({title: 'Hello world'});
post.save(function(err, data) { post.save(function(err, data) {
console.log(err ? err : data); console.log(err ? err : data);
}); });
}); });
Post.findOne({ where: { published: false }, order: 'date DESC' }, function(err, data) { Post.findOne({where: {published: false}, order: 'date DESC'}, function(err, data) {
console.log(data); console.log(data);
}); });
User.create({ name: 'Jeff', age: 12 }, function(err, data) { User.create({name: 'Jeff', age: 12}, function(err, data) {
if (err) { if (err) {
console.log(err); console.log(err);
return; return;
} }
console.log(data); console.log(data);
var post = data.posts.build({ title: 'My Post' }); var post = data.posts.build({title: 'My Post'});
console.log(post); console.log(post);
}); });
User.create({ name: 'Ray' }, function(err, data) { User.create({name: 'Ray'}, function(err, data) {
console.log(data); console.log(data);
}); });
User.scope('minors', { where: { age: { lte: 16 }}, include: 'posts' }); User.scope('minors', {where: {age: {lte: 16}}, include: 'posts'});
User.minors(function(err, kids) { User.minors(function(err, kids) {
console.log('Kids: ', kids); console.log('Kids: ', kids);
}); });
var Article = ds.define('Article', { title: String }); var Article = ds.define('Article', {title: String});
var Tag = ds.define('Tag', { name: String }); var Tag = ds.define('Tag', {name: String});
Article.hasAndBelongsToMany('tags'); Article.hasAndBelongsToMany('tags');
Article.create(function(e, article) { Article.create(function(e, article) {
article.tags.create({ name: 'popular' }, function(err, data) { article.tags.create({name: 'popular'}, function(err, data) {
Article.findOne(function(e, article) { Article.findOne(function(e, article) {
article.tags(function(e, tags) { article.tags(function(e, tags) {
console.log(tags); console.log(tags);
@ -112,9 +114,9 @@ Color = modelBuilder.define('Color', {
// attach // attach
ds.attach(Color); ds.attach(Color);
Color.create({ name: 'red' }); Color.create({name: 'red'});
Color.create({ name: 'green' }); Color.create({name: 'green'});
Color.create({ name: 'blue' }); Color.create({name: 'blue'});
Color.all(function(err, colors) { Color.all(function(err, colors) {
console.log(colors); console.log(colors);

View File

@ -3,37 +3,39 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var jdb = require('../index'); var jdb = require('../index');
var User, Post, Passport, City, Street, Building; var User, Post, Passport, City, Street, Building;
var nbSchemaRequests = 0; var nbSchemaRequests = 0;
setup(function() { setup(function() {
Passport.find({ include: 'owner' }, function(err, passports) { Passport.find({include: 'owner'}, function(err, passports) {
console.log('passports.owner', passports); console.log('passports.owner', passports);
}); });
User.find({ include: 'posts' }, function(err, users) { User.find({include: 'posts'}, function(err, users) {
console.log('users.posts', users); console.log('users.posts', users);
}); });
Passport.find({ include: { owner: 'posts' }}, function(err, passports) { Passport.find({include: {owner: 'posts'}}, function(err, passports) {
console.log('passports.owner.posts', passports); console.log('passports.owner.posts', passports);
}); });
Passport.find({ Passport.find({
include: { owner: { posts: 'author' }}, include: {owner: {posts: 'author'}},
}, function(err, passports) { }, function(err, passports) {
console.log('passports.owner.posts.author', passports); console.log('passports.owner.posts.author', passports);
}); });
User.find({ include: ['posts', 'passports'] }, function(err, users) { User.find({include: ['posts', 'passports']}, function(err, users) {
console.log('users.passports && users.posts', users); console.log('users.passports && users.posts', users);
}); });
}); });
function setup(done) { function setup(done) {
var db = new jdb.DataSource({ connector: 'memory' }); var db = new jdb.DataSource({connector: 'memory'});
City = db.define('City'); City = db.define('City');
Street = db.define('Street'); Street = db.define('Street');
Building = db.define('Building'); Building = db.define('Building');
@ -48,10 +50,10 @@ function setup(done) {
title: String, title: String,
}); });
Passport.belongsTo('owner', { model: User }); Passport.belongsTo('owner', {model: User});
User.hasMany('passports', { foreignKey: 'ownerId' }); User.hasMany('passports', {foreignKey: 'ownerId'});
User.hasMany('posts', { foreignKey: 'userId' }); User.hasMany('posts', {foreignKey: 'userId'});
Post.belongsTo('author', { model: User, foreignKey: 'userId' }); Post.belongsTo('author', {model: User, foreignKey: 'userId'});
db.automigrate(function() { db.automigrate(function() {
var createdUsers = []; var createdUsers = [];
@ -62,11 +64,11 @@ function setup(done) {
clearAndCreate( clearAndCreate(
User, User,
[ [
{ name: 'User A', age: 21 }, {name: 'User A', age: 21},
{ name: 'User B', age: 22 }, {name: 'User B', age: 22},
{ name: 'User C', age: 23 }, {name: 'User C', age: 23},
{ name: 'User D', age: 24 }, {name: 'User D', age: 24},
{ name: 'User E', age: 25 }, {name: 'User E', age: 25},
], ],
function(items) { function(items) {
createdUsers = items; createdUsers = items;
@ -79,9 +81,9 @@ function setup(done) {
clearAndCreate( clearAndCreate(
Passport, Passport,
[ [
{ number: '1', ownerId: createdUsers[0].id }, {number: '1', ownerId: createdUsers[0].id},
{ number: '2', ownerId: createdUsers[1].id }, {number: '2', ownerId: createdUsers[1].id},
{ number: '3' }, {number: '3'},
], ],
function(items) { function(items) {
createdPassports = items; createdPassports = items;
@ -94,11 +96,11 @@ function setup(done) {
clearAndCreate( clearAndCreate(
Post, Post,
[ [
{ title: 'Post A', userId: createdUsers[0].id }, {title: 'Post A', userId: createdUsers[0].id},
{ title: 'Post B', userId: createdUsers[0].id }, {title: 'Post B', userId: createdUsers[0].id},
{ title: 'Post C', userId: createdUsers[0].id }, {title: 'Post C', userId: createdUsers[0].id},
{ title: 'Post D', userId: createdUsers[1].id }, {title: 'Post D', userId: createdUsers[1].id},
{ title: 'Post E' }, {title: 'Post E'},
], ],
function(items) { function(items) {
createdPosts = items; createdPosts = items;

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var path = require('path'), var path = require('path'),
fs = require('fs'), fs = require('fs'),
DataSource = require('../lib/datasource').DataSource; DataSource = require('../lib/datasource').DataSource;

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder; var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
@ -32,9 +34,9 @@ var User = modelBuilder.define('User', {
var user = new User({ var user = new User({
name: 'Joe', name: 'Joe',
age: 20, age: 20,
address: { street: '123 Main St', 'city': 'San Jose', state: 'CA' }, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'},
emails: [ emails: [
{ label: 'work', email: 'xyz@sample.com' }, {label: 'work', email: 'xyz@sample.com'},
], ],
friends: ['John', 'Mary'], friends: ['John', 'Mary'],
}); });

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var DataSource = require('../index').DataSource; var DataSource = require('../index').DataSource;
var ds = new DataSource('memory'); var ds = new DataSource('memory');
@ -20,43 +22,43 @@ Order.belongsTo(Customer);
var order1, order2, order3; var order1, order2, order3;
Customer.create({ name: 'John' }, function(err, customer) { Customer.create({name: 'John'}, function(err, customer) {
Order.create({ customerId: customer.id, orderDate: new Date(), items: ['Book'] }, function(err, order) { Order.create({customerId: customer.id, orderDate: new Date(), items: ['Book']}, function(err, order) {
order1 = order; order1 = order;
order.customer(console.log); order.customer(console.log);
order.customer(true, console.log); order.customer(true, console.log);
Customer.create({ name: 'Mary' }, function(err, customer2) { Customer.create({name: 'Mary'}, function(err, customer2) {
order.customer(customer2); order.customer(customer2);
order.customer(console.log); order.customer(console.log);
}); });
}); });
Order.create({ orderDate: new Date(), items: ['Phone'] }, function(err, order) { Order.create({orderDate: new Date(), items: ['Phone']}, function(err, order) {
order.customer.create({ name: 'Smith' }, function(err, customer2) { order.customer.create({name: 'Smith'}, function(err, customer2) {
console.log(order, customer2); console.log(order, customer2);
order.save(function(err, order) { order.save(function(err, order) {
order2 = order; order2 = order;
}); });
}); });
var customer3 = order.customer.build({ name: 'Tom' }); var customer3 = order.customer.build({name: 'Tom'});
console.log('Customer 3', customer3); console.log('Customer 3', customer3);
}); });
}); });
Customer.hasMany(Order, { as: 'orders', foreignKey: 'customerId' }); Customer.hasMany(Order, {as: 'orders', foreignKey: 'customerId'});
Customer.create({ name: 'Ray' }, function(err, customer) { Customer.create({name: 'Ray'}, function(err, customer) {
Order.create({ customerId: customer.id, qty: 3, orderDate: new Date() }, function(err, order) { Order.create({customerId: customer.id, qty: 3, orderDate: new Date()}, function(err, order) {
order3 = order; order3 = order;
customer.orders(console.log); customer.orders(console.log);
customer.orders.create({ orderDate: new Date(), qty: 4 }, function(err, order) { customer.orders.create({orderDate: new Date(), qty: 4}, function(err, order) {
console.log(order); console.log(order);
Customer.include([customer], 'orders', function(err, results) { Customer.include([customer], 'orders', function(err, results) {
console.log('Results: ', results); console.log('Results: ', results);
}); });
customer.orders({ where: { qty: 4 }}, function(err, results) { customer.orders({where: {qty: 4}}, function(err, results) {
console.log('customer.orders', results); console.log('customer.orders', results);
}); });
customer.orders.findById(order3.id, console.log); customer.orders.findById(order3.id, console.log);
@ -82,29 +84,29 @@ var Appointment = ds.createModel('Appointment', {
Appointment.belongsTo(Patient); Appointment.belongsTo(Patient);
Appointment.belongsTo(Physician); Appointment.belongsTo(Physician);
Physician.hasMany(Patient, { through: Appointment }); Physician.hasMany(Patient, {through: Appointment});
Patient.hasMany(Physician, { through: Appointment }); Patient.hasMany(Physician, {through: Appointment});
Physician.create({ name: 'Dr John' }, function(err, physician1) { Physician.create({name: 'Dr John'}, function(err, physician1) {
Physician.create({ name: 'Dr Smith' }, function(err, physician2) { Physician.create({name: 'Dr Smith'}, function(err, physician2) {
Patient.create({ name: 'Mary' }, function(err, patient1) { Patient.create({name: 'Mary'}, function(err, patient1) {
Patient.create({ name: 'Ben' }, function(err, patient2) { Patient.create({name: 'Ben'}, function(err, patient2) {
Appointment.create( Appointment.create(
{ appointmentDate: new Date(), physicianId: physician1.id, patientId: patient1.id }, {appointmentDate: new Date(), physicianId: physician1.id, patientId: patient1.id},
function(err, appt1) { function(err, appt1) {
Appointment.create( Appointment.create(
{ appointmentDate: new Date(), physicianId: physician1.id, patientId: patient2.id }, {appointmentDate: new Date(), physicianId: physician1.id, patientId: patient2.id},
function(err, appt2) { function(err, appt2) {
physician1.patients(console.log); physician1.patients(console.log);
physician1.patients({ where: { name: 'Mary' }}, console.log); physician1.patients({where: {name: 'Mary'}}, console.log);
patient1.physicians(console.log); patient1.physicians(console.log);
// Build an appointment? // Build an appointment?
var patient3 = patient1.physicians.build({ name: 'Dr X' }); var patient3 = patient1.physicians.build({name: 'Dr X'});
console.log('Physician 3: ', patient3, patient3.constructor.modelName); console.log('Physician 3: ', patient3, patient3.constructor.modelName);
// Create a physician? // Create a physician?
patient1.physicians.create({ name: 'Dr X' }, function(err, patient4) { patient1.physicians.create({name: 'Dr X'}, function(err, patient4) {
console.log('Physician 4: ', patient4, patient4.constructor.modelName); console.log('Physician 4: ', patient4, patient4.constructor.modelName);
}); });
}); });
@ -125,22 +127,22 @@ var Part = ds.createModel('Part', {
Assembly.hasAndBelongsToMany(Part); Assembly.hasAndBelongsToMany(Part);
Part.hasAndBelongsToMany(Assembly); Part.hasAndBelongsToMany(Assembly);
Assembly.create({ name: 'car' }, function(err, assembly) { Assembly.create({name: 'car'}, function(err, assembly) {
Part.create({ partNumber: 'engine' }, function(err, part) { Part.create({partNumber: 'engine'}, function(err, part) {
assembly.parts.add(part, function(err) { assembly.parts.add(part, function(err) {
assembly.parts(function(err, parts) { assembly.parts(function(err, parts) {
console.log('Parts: ', parts); console.log('Parts: ', parts);
}); });
// Build an part? // Build an part?
var part3 = assembly.parts.build({ partNumber: 'door' }); var part3 = assembly.parts.build({partNumber: 'door'});
console.log('Part3: ', part3, part3.constructor.modelName); console.log('Part3: ', part3, part3.constructor.modelName);
// Create a part? // Create a part?
assembly.parts.create({ partNumber: 'door' }, function(err, part4) { assembly.parts.create({partNumber: 'door'}, function(err, part4) {
console.log('Part4: ', part4, part4.constructor.modelName); console.log('Part4: ', part4, part4.constructor.modelName);
Assembly.find({ include: 'parts' }, function(err, assemblies) { Assembly.find({include: 'parts'}, function(err, assemblies) {
console.log('Assemblies: ', assemblies); console.log('Assemblies: ', assemblies);
}); });
}); });

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var SG = require('strong-globalize'); var SG = require('strong-globalize');
SG.SetRootDir(__dirname); SG.SetRootDir(__dirname);

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
// A lightweight alternative to "depd" that works in the browser // A lightweight alternative to "depd" that works in the browser
module.exports = function depd(namespace) { module.exports = function depd(namespace) {
var warned = {}; var warned = {};

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var util = require('util'); var util = require('util');
var Connector = require('loopback-connector').Connector; var Connector = require('loopback-connector').Connector;
@ -107,7 +109,7 @@ Memory.prototype.loadFromFile = function(callback) {
var localStorage = hasLocalStorage && this.settings.localStorage; var localStorage = hasLocalStorage && this.settings.localStorage;
if (self.settings.file) { if (self.settings.file) {
fs.readFile(self.settings.file, { encoding: 'utf8', flag: 'r' }, function(err, data) { fs.readFile(self.settings.file, {encoding: 'utf8', flag: 'r'}, function(err, data) {
if (err && err.code !== 'ENOENT') { if (err && err.code !== 'ENOENT') {
callback && callback(err); callback && callback(err);
} else { } else {
@ -241,12 +243,12 @@ Memory.prototype.updateOrCreate = function(model, data, options, callback) {
this.exists(model, self.getIdValue(model, data), options, function(err, exists) { this.exists(model, self.getIdValue(model, data), options, function(err, exists) {
if (exists) { if (exists) {
self.save(model, data, options, function(err, data) { self.save(model, data, options, function(err, data) {
callback(err, data, { isNewInstance: false }); callback(err, data, {isNewInstance: false});
}); });
} else { } else {
self.create(model, data, options, function(err, id) { self.create(model, data, options, function(err, id) {
self.setIdValue(model, data, id); self.setIdValue(model, data, id);
callback(err, data, { isNewInstance: true }); callback(err, data, {isNewInstance: true});
}); });
} }
}); });
@ -256,21 +258,21 @@ Memory.prototype.patchOrCreateWithWhere =
Memory.prototype.upsertWithWhere = function(model, where, data, options, callback) { Memory.prototype.upsertWithWhere = function(model, where, data, options, callback) {
var self = this; var self = this;
var primaryKey = this.idName(model); var primaryKey = this.idName(model);
var filter = { where: where }; var filter = {where: where};
var nodes = self._findAllSkippingIncludes(model, filter); var nodes = self._findAllSkippingIncludes(model, filter);
if (nodes.length === 0) { if (nodes.length === 0) {
return self._createSync(model, data, function(err, id) { return self._createSync(model, data, function(err, id) {
if (err) return process.nextTick(function() { callback(err); }); if (err) return process.nextTick(function() { callback(err); });
self.saveToFile(id, function(err, id) { self.saveToFile(id, function(err, id) {
self.setIdValue(model, data, id); self.setIdValue(model, data, id);
callback(err, self.fromDb(model, data), { isNewInstance: true }); callback(err, self.fromDb(model, data), {isNewInstance: true});
}); });
}); });
} }
if (nodes.length === 1) { if (nodes.length === 1) {
var primaryKeyValue = nodes[0][primaryKey]; var primaryKeyValue = nodes[0][primaryKey];
self.updateAttributes(model, primaryKeyValue, data, options, function(err, data) { self.updateAttributes(model, primaryKeyValue, data, options, function(err, data) {
callback(err, data, { isNewInstance: false }); callback(err, data, {isNewInstance: false});
}); });
} else { } else {
process.nextTick(function() { process.nextTick(function() {
@ -323,7 +325,7 @@ Memory.prototype.save = function save(model, data, options, callback) {
} }
this.collection(model)[id] = serialize(data); this.collection(model)[id] = serialize(data);
this.saveToFile(data, function(err) { this.saveToFile(data, function(err) {
callback(err, self.fromDb(model, data), { isNewInstance: !modelData }); callback(err, self.fromDb(model, data), {isNewInstance: !modelData});
}); });
}; };
@ -342,7 +344,7 @@ Memory.prototype.find = function find(model, id, options, callback) {
Memory.prototype.destroy = function destroy(model, id, options, callback) { Memory.prototype.destroy = function destroy(model, id, options, callback) {
var exists = this.collection(model)[id]; var exists = this.collection(model)[id];
delete this.collection(model)[id]; delete this.collection(model)[id];
this.saveToFile({ count: exists ? 1 : 0 }, callback); this.saveToFile({count: exists ? 1 : 0}, callback);
}; };
Memory.prototype.fromDb = function(model, data) { Memory.prototype.fromDb = function(model, data) {
@ -412,7 +414,7 @@ Memory.prototype._findAllSkippingIncludes = function(model, filter) {
key = key.replace(/\s+(A|DE)SC/i, ''); key = key.replace(/\s+(A|DE)SC/i, '');
if (m[1].toLowerCase() === 'de') reverse = -1; if (m[1].toLowerCase() === 'de') reverse = -1;
} }
orders[i] = { 'key': key, 'reverse': reverse }; orders[i] = {'key': key, 'reverse': reverse};
}); });
nodes = nodes.sort(sorting.bind(orders)); nodes = nodes.sort(sorting.bind(orders));
} }
@ -485,12 +487,12 @@ function applyFilter(filter) {
if (Array.isArray(where[key])) { if (Array.isArray(where[key])) {
if (key === 'and') { if (key === 'and') {
return where[key].every(function(cond) { return where[key].every(function(cond) {
return applyFilter({ where: cond })(obj); return applyFilter({where: cond})(obj);
}); });
} }
if (key === 'or') { if (key === 'or') {
return where[key].some(function(cond) { return where[key].some(function(cond) {
return applyFilter({ where: cond })(obj); return applyFilter({where: cond})(obj);
}); });
} }
} }
@ -507,7 +509,7 @@ function applyFilter(filter) {
return true; return true;
} }
return value.some(function(v, i) { return value.some(function(v, i) {
var filter = { where: {}}; var filter = {where: {}};
filter.where[i] = matcher; filter.where[i] = matcher;
return applyFilter(filter)(value); return applyFilter(filter)(value);
}); });
@ -522,7 +524,7 @@ function applyFilter(filter) {
var dotIndex = key.indexOf('.'); var dotIndex = key.indexOf('.');
var subValue = obj[key.substring(0, dotIndex)]; var subValue = obj[key.substring(0, dotIndex)];
if (dotIndex !== -1 && Array.isArray(subValue)) { if (dotIndex !== -1 && Array.isArray(subValue)) {
var subFilter = { where: {}}; var subFilter = {where: {}};
var subKey = key.substring(dotIndex + 1); var subKey = key.substring(dotIndex + 1);
subFilter.where[subKey] = where[key]; subFilter.where[subKey] = where[key];
return subValue.some(applyFilter(subFilter)); return subValue.some(applyFilter(subFilter));
@ -606,8 +608,8 @@ function applyFilter(filter) {
} }
if ('between' in example) { if ('between' in example) {
return (testInEquality({ gte: example.between[0] }, value) && return (testInEquality({gte: example.between[0]}, value) &&
testInEquality({ lte: example.between[1] }, value)); testInEquality({lte: example.between[1]}, value));
} }
if (example.like || example.nlike) { if (example.like || example.nlike) {
@ -684,7 +686,7 @@ Memory.prototype.destroyAll = function destroyAll(model, where, options, callbac
var filter = null; var filter = null;
var count = 0; var count = 0;
if (where) { if (where) {
filter = applyFilter({ where: where }); filter = applyFilter({where: where});
Object.keys(cache).forEach(function(id) { Object.keys(cache).forEach(function(id) {
if (!filter || filter(this.fromDb(model, cache[id]))) { if (!filter || filter(this.fromDb(model, cache[id]))) {
count++; count++;
@ -695,14 +697,14 @@ Memory.prototype.destroyAll = function destroyAll(model, where, options, callbac
count = Object.keys(cache).length; count = Object.keys(cache).length;
this.collection(model, {}); this.collection(model, {});
} }
this.saveToFile({ count: count }, callback); this.saveToFile({count: count}, callback);
}; };
Memory.prototype.count = function count(model, where, options, callback) { Memory.prototype.count = function count(model, where, options, callback) {
var cache = this.collection(model); var cache = this.collection(model);
var data = Object.keys(cache); var data = Object.keys(cache);
if (where) { if (where) {
var filter = { where: where }; var filter = {where: where};
data = data.map(function(id) { data = data.map(function(id) {
return this.fromDb(model, cache[id]); return this.fromDb(model, cache[id]);
}.bind(this)); }.bind(this));
@ -719,7 +721,7 @@ Memory.prototype.update =
var cache = this.collection(model); var cache = this.collection(model);
var filter = null; var filter = null;
where = where || {}; where = where || {};
filter = applyFilter({ where: where }); filter = applyFilter({where: where});
var ids = Object.keys(cache); var ids = Object.keys(cache);
var count = 0; var count = 0;
@ -736,7 +738,7 @@ Memory.prototype.update =
} }
}, function(err) { }, function(err) {
if (err) return cb(err); if (err) return cb(err);
self.saveToFile({ count: count }, cb); self.saveToFile({count: count}, cb);
}); });
}; };
@ -800,7 +802,7 @@ Memory.prototype.replaceOrCreate = function(model, data, options, callback) {
var self = this; var self = this;
var idName = self.idNames(model)[0]; var idName = self.idNames(model)[0];
var idValue = self.getIdValue(model, data); var idValue = self.getIdValue(model, data);
var filter = { where: {}}; var filter = {where: {}};
filter.where[idName] = idValue; filter.where[idName] = idValue;
var nodes = self._findAllSkippingIncludes(model, filter); var nodes = self._findAllSkippingIncludes(model, filter);
var found = nodes[0]; var found = nodes[0];
@ -812,14 +814,14 @@ Memory.prototype.replaceOrCreate = function(model, data, options, callback) {
if (err) return process.nextTick(function() { cb(err); }); if (err) return process.nextTick(function() { cb(err); });
self.saveToFile(id, function(err, id) { self.saveToFile(id, function(err, id) {
self.setIdValue(model, data, id); self.setIdValue(model, data, id);
callback(err, self.fromDb(model, data), { isNewInstance: true }); callback(err, self.fromDb(model, data), {isNewInstance: true});
}); });
}); });
} }
var id = self.getIdValue(model, data); var id = self.getIdValue(model, data);
self.collection(model)[id] = serialize(data); self.collection(model)[id] = serialize(data);
self.saveToFile(data, function(err) { self.saveToFile(data, function(err) {
callback(err, self.fromDb(model, data), { isNewInstance: false }); callback(err, self.fromDb(model, data), {isNewInstance: false});
}); });
}; };

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var util = require('util'); var util = require('util');
var Connector = require('loopback-connector').Connector; var Connector = require('loopback-connector').Connector;
@ -104,7 +106,7 @@ Transient.prototype.save = function save(model, data, callback) {
Transient.prototype.update = Transient.prototype.update =
Transient.prototype.updateAll = function updateAll(model, where, data, cb) { Transient.prototype.updateAll = function updateAll(model, where, data, cb) {
var count = 0; var count = 0;
this.flush('update', { count: count }, cb); this.flush('update', {count: count}, cb);
}; };
Transient.prototype.updateAttributes = function updateAttributes(model, id, data, cb) { Transient.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {

View File

@ -107,7 +107,7 @@ function setIdValue(m, data, value) {
function byIdQuery(m, id) { function byIdQuery(m, id) {
var pk = idName(m); var pk = idName(m);
var query = { where: {}}; var query = {where: {}};
query.where[pk] = id; query.where[pk] = id;
return query; return query;
} }
@ -252,7 +252,7 @@ DataAccessObject.create = function(data, options, cb) {
async.map(data, function(item, done) { async.map(data, function(item, done) {
self.create(item, options, function(err, result) { self.create(item, options, function(err, result) {
// Collect all errors and results // Collect all errors and results
done(null, { err: err, result: result || item }); done(null, {err: err, result: result || item});
}); });
}, function(err, results) { }, function(err, results) {
if (err) { if (err) {
@ -508,7 +508,7 @@ DataAccessObject.upsert = function(data, options, cb) {
var update = data; var update = data;
var inst = data; var inst = data;
if (!(data instanceof Model)) { if (!(data instanceof Model)) {
inst = new Model(data, { applyDefaultValues: false }); inst = new Model(data, {applyDefaultValues: false});
} }
update = inst.toObject(false); update = inst.toObject(false);
@ -581,7 +581,7 @@ DataAccessObject.upsert = function(data, options, cb) {
var obj; var obj;
if (data && !(data instanceof Model)) { if (data && !(data instanceof Model)) {
inst._initProperties(data, { persisted: true }); inst._initProperties(data, {persisted: true});
obj = inst; obj = inst;
} else { } else {
obj = data; obj = data;
@ -605,11 +605,11 @@ DataAccessObject.upsert = function(data, options, cb) {
} }
}); });
} else { } else {
var opts = { notify: false }; var opts = {notify: false};
if (ctx.options && ctx.options.transaction) { if (ctx.options && ctx.options.transaction) {
opts.transaction = ctx.options.transaction; opts.transaction = ctx.options.transaction;
} }
Model.findOne({ where: ctx.query.where }, opts, function(err, inst) { Model.findOne({where: ctx.query.where}, opts, function(err, inst) {
if (err) { if (err) {
return cb(err); return cb(err);
} }
@ -674,7 +674,7 @@ DataAccessObject.upsertWithWhere = function(where, data, options, cb) {
var Model = this; var Model = this;
var connector = Model.getConnector(); var connector = Model.getConnector();
var modelName = Model.modelName; var modelName = Model.modelName;
var query = { where: where }; var query = {where: where};
var context = { var context = {
Model: Model, Model: Model,
query: query, query: query,
@ -699,7 +699,7 @@ DataAccessObject.upsertWithWhere = function(where, data, options, cb) {
var update = data; var update = data;
var inst = data; var inst = data;
if (!(data instanceof Model)) { if (!(data instanceof Model)) {
inst = new Model(data, { applyDefaultValues: false }); inst = new Model(data, {applyDefaultValues: false});
} }
update = inst.toObject(false); update = inst.toObject(false);
Model.applyScope(query); Model.applyScope(query);
@ -753,7 +753,7 @@ DataAccessObject.upsertWithWhere = function(where, data, options, cb) {
if (err) return cb(err); if (err) return cb(err);
var obj; var obj;
if (contxt.data && !(contxt.data instanceof Model)) { if (contxt.data && !(contxt.data instanceof Model)) {
inst._initProperties(contxt.data, { persisted: true }); inst._initProperties(contxt.data, {persisted: true});
obj = inst; obj = inst;
} else { } else {
obj = contxt.data; obj = contxt.data;
@ -772,11 +772,11 @@ DataAccessObject.upsertWithWhere = function(where, data, options, cb) {
} }
}); });
} else { } else {
var opts = { notify: false }; var opts = {notify: false};
if (ctx.options && ctx.options.transaction) { if (ctx.options && ctx.options.transaction) {
opts.transaction = ctx.options.transaction; opts.transaction = ctx.options.transaction;
} }
self.find({ where: ctx.query.where }, opts, function(err, instances) { self.find({where: ctx.query.where}, opts, function(err, instances) {
if (err) return cb(err); if (err) return cb(err);
var modelsLength = instances.length; var modelsLength = instances.length;
if (modelsLength === 0) { if (modelsLength === 0) {
@ -926,7 +926,7 @@ DataAccessObject.replaceOrCreate = function replaceOrCreate(data, options, cb) {
var obj; var obj;
if (data && !(data instanceof Model)) { if (data && !(data instanceof Model)) {
inst._initProperties(data, { persisted: true }); inst._initProperties(data, {persisted: true});
obj = inst; obj = inst;
} else { } else {
obj = data; obj = data;
@ -951,11 +951,11 @@ DataAccessObject.replaceOrCreate = function replaceOrCreate(data, options, cb) {
} }
}); });
} else { } else {
var opts = { notify: false }; var opts = {notify: false};
if (ctx.options && ctx.options.transaction) { if (ctx.options && ctx.options.transaction) {
opts.transaction = ctx.options.transaction; opts.transaction = ctx.options.transaction;
} }
Model.findOne({ where: ctx.query.where }, opts, function(err, found) { Model.findOne({where: ctx.query.where}, opts, function(err, found) {
if (err) return cb(err); if (err) return cb(err);
if (!isOriginalQuery) { if (!isOriginalQuery) {
// The custom query returned from a hook may hide the fact that // The custom query returned from a hook may hide the fact that
@ -1000,14 +1000,14 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
// findOrCreate(data); // findOrCreate(data);
// query will be built from data, and method will return Promise // query will be built from data, and method will return Promise
data = query; data = query;
query = { where: data }; query = {where: data};
} else if (options === undefined && cb === undefined) { } else if (options === undefined && cb === undefined) {
if (typeof data === 'function') { if (typeof data === 'function') {
// findOrCreate(data, cb); // findOrCreate(data, cb);
// query will be built from data // query will be built from data
cb = data; cb = data;
data = query; data = query;
query = { where: data }; query = {where: data};
} }
} else if (cb === undefined) { } else if (cb === undefined) {
if (typeof options === 'function') { if (typeof options === 'function') {
@ -1018,7 +1018,7 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
} }
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
query = query || { where: {}}; query = query || {where: {}};
data = data || {}; data = data || {};
options = options || {}; options = options || {};
@ -1049,8 +1049,8 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
var obj, Model = self.lookupModel(data); var obj, Model = self.lookupModel(data);
if (data) { if (data) {
obj = new Model(data, { fields: query.fields, applySetters: false, obj = new Model(data, {fields: query.fields, applySetters: false,
persisted: true }); persisted: true});
} }
if (created) { if (created) {
@ -1336,9 +1336,9 @@ DataAccessObject.findByIds = function(ids, query, options, cb) {
return cb.promise; return cb.promise;
} }
var filter = { where: {}}; var filter = {where: {}};
var pk = idName(this); var pk = idName(this);
filter.where[pk] = { inq: [].concat(ids) }; filter.where[pk] = {inq: [].concat(ids)};
mergeQuery(filter, query || {}); mergeQuery(filter, query || {});
// to know if the result need to be sorted by ids or not // to know if the result need to be sorted by ids or not
@ -2059,7 +2059,7 @@ DataAccessObject.destroyAll = function destroyAll(where, options, cb) {
var hookState = {}; var hookState = {};
var query = { where: where }; var query = {where: where};
this.applyScope(query); this.applyScope(query);
where = query.where; where = query.where;
@ -2073,7 +2073,7 @@ DataAccessObject.destroyAll = function destroyAll(where, options, cb) {
if (options.notify === false) { if (options.notify === false) {
doDelete(where); doDelete(where);
} else { } else {
query = { where: whereIsEmpty(where) ? {} : where }; query = {where: whereIsEmpty(where) ? {} : where};
var context = { var context = {
Model: Model, Model: Model,
query: query, query: query,
@ -2256,7 +2256,7 @@ DataAccessObject.count = function(where, options, cb) {
var hookState = {}; var hookState = {};
var query = { where: where }; var query = {where: where};
this.applyScope(query); this.applyScope(query);
where = query.where; where = query.where;
@ -2272,7 +2272,7 @@ DataAccessObject.count = function(where, options, cb) {
var context = { var context = {
Model: Model, Model: Model,
query: { where: where }, query: {where: where},
hookState: hookState, hookState: hookState,
options: options, options: options,
}; };
@ -2394,7 +2394,7 @@ DataAccessObject.prototype.save = function(options, cb) {
Model.notifyObserversOf('loaded', context, function(err) { Model.notifyObserversOf('loaded', context, function(err) {
if (err) return cb(err); if (err) return cb(err);
inst._initProperties(data, { persisted: true }); inst._initProperties(data, {persisted: true});
var context = { var context = {
Model: Model, Model: Model,
@ -2502,7 +2502,7 @@ DataAccessObject.updateAll = function(where, data, options, cb) {
var hookState = {}; var hookState = {};
var query = { where: where }; var query = {where: where};
this.applyScope(query); this.applyScope(query);
this.applyProperties(data); this.applyProperties(data);
@ -2510,7 +2510,7 @@ DataAccessObject.updateAll = function(where, data, options, cb) {
var context = { var context = {
Model: Model, Model: Model,
query: { where: where }, query: {where: where},
hookState: hookState, hookState: hookState,
options: options, options: options,
}; };
@ -2653,7 +2653,7 @@ DataAccessObject.prototype.remove =
// A hook modified the query, it is no longer // A hook modified the query, it is no longer
// a simple 'delete model with the given id'. // a simple 'delete model with the given id'.
// We must switch to full query-based delete. // We must switch to full query-based delete.
Model.deleteAll(where, { notify: false }, function(err, info) { Model.deleteAll(where, {notify: false}, function(err, info) {
if (err) return cb(err, false); if (err) return cb(err, false);
var deleted = info && info.count > 0; var deleted = info && info.count > 0;
if (Model.settings.strictDelete && !deleted) { if (Model.settings.strictDelete && !deleted) {
@ -2817,7 +2817,7 @@ DataAccessObject.replaceById = function(id, data, options, cb) {
if (!data[pkName]) data[pkName] = id; if (!data[pkName]) data[pkName] = id;
var Model = this; var Model = this;
var inst = new Model(data, { persisted: true }); var inst = new Model(data, {persisted: true});
var enforced = {}; var enforced = {};
this.applyProperties(enforced, inst); this.applyProperties(enforced, inst);
inst.setAttributes(enforced); inst.setAttributes(enforced);

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
/*! /*!
* Module dependencies * Module dependencies
*/ */
@ -520,7 +522,7 @@ DataSource.prototype.setupDataAccess = function(modelClass, settings) {
forceId = true; forceId = true;
} }
if (forceId) { if (forceId) {
modelClass.validatesAbsenceOf(idName, { if: 'isNewRecord' }); modelClass.validatesAbsenceOf(idName, {if: 'isNewRecord'});
} }
} }
if (this.connector.define) { if (this.connector.define) {
@ -652,7 +654,7 @@ DataSource.prototype.mixin = function(ModelCtor) {
var DAO = this.DataAccessObject; var DAO = this.DataAccessObject;
// mixin DAO // mixin DAO
jutil.mixin(ModelCtor, DAO, { proxyFunctions: true, override: true }); jutil.mixin(ModelCtor, DAO, {proxyFunctions: true, override: true});
// decorate operations as alias functions // decorate operations as alias functions
Object.keys(ops).forEach(function(name) { Object.keys(ops).forEach(function(name) {
@ -1424,7 +1426,7 @@ DataSource.prototype.discoverSchemas = function(modelName, options, cb) {
var key = fk.pkOwner + '.' + fk.pkTableName; var key = fk.pkOwner + '.' + fk.pkTableName;
if (!options.visited.hasOwnProperty(key) && !otherTables.hasOwnProperty(key)) { if (!options.visited.hasOwnProperty(key) && !otherTables.hasOwnProperty(key)) {
otherTables[key] = { owner: fk.pkOwner, tableName: fk.pkTableName }; otherTables[key] = {owner: fk.pkOwner, tableName: fk.pkTableName};
} }
}); });
} }
@ -1575,7 +1577,7 @@ DataSource.prototype.discoverSchemasSync = function(modelName, options) {
var key = fk.pkOwner + '.' + fk.pkTableName; var key = fk.pkOwner + '.' + fk.pkTableName;
if (!options.visited.hasOwnProperty(key) && !otherTables.hasOwnProperty(key)) { if (!options.visited.hasOwnProperty(key) && !otherTables.hasOwnProperty(key)) {
otherTables[key] = { owner: fk.pkOwner, tableName: fk.pkTableName }; otherTables[key] = {owner: fk.pkOwner, tableName: fk.pkTableName};
} }
}); });
} }
@ -1833,7 +1835,7 @@ DataSource.prototype.defineForeignKey = function defineForeignKey(className, key
return; return;
} }
var fkDef = { type: pkType }; var fkDef = {type: pkType};
var foreignMeta = this.columnMetadata(foreignClassName, pkName); var foreignMeta = this.columnMetadata(foreignClassName, pkName);
if (foreignMeta && (foreignMeta.dataType || foreignMeta.dataLength)) { if (foreignMeta && (foreignMeta.dataType || foreignMeta.dataLength)) {
fkDef[this.connector.name] = {}; fkDef[this.connector.name] = {};

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var assert = require('assert'); var assert = require('assert');
/*! /*!
@ -57,7 +59,7 @@ exports.filter = function(arr, filter) {
if (typeof loc.lat !== 'number') return; if (typeof loc.lat !== 'number') return;
if (typeof loc.lng !== 'number') return; if (typeof loc.lng !== 'number') return;
var d = GeoPoint.distanceBetween(origin, loc, { type: unit }); var d = GeoPoint.distanceBetween(origin, loc, {type: unit});
if (max && d > max) { if (max && d > max) {
// dont add // dont add

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var deprecated = require('depd')('loopback-datasource-juggler'); var deprecated = require('depd')('loopback-datasource-juggler');
var g = require('strong-globalize')(); var g = require('strong-globalize')();

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var async = require('async'); var async = require('async');
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var utils = require('./utils'); var utils = require('./utils');
@ -328,7 +330,7 @@ Inclusion.include = function(objects, include, options, cb) {
} }
}); });
} }
utils.mergeQuery(filter, includeScope, { fields: false }); utils.mergeQuery(filter, includeScope, {fields: false});
} }
//Let's add a placeholder where query //Let's add a placeholder where query
filter.where = filter.where || {}; filter.where = filter.where || {};
@ -736,7 +738,7 @@ Inclusion.include = function(objects, include, options, cb) {
* @param callback * @param callback
*/ */
function processPolymorphicType(modelType, callback) { function processPolymorphicType(modelType, callback) {
var typeFilter = { where: {}}; var typeFilter = {where: {}};
utils.mergeQuery(typeFilter, filter); utils.mergeQuery(typeFilter, filter);
var targetIds = targetIdsByType[modelType]; var targetIds = targetIdsByType[modelType];
typeFilter.where[relation.keyTo] = { typeFilter.where[relation.keyTo] = {
@ -1012,7 +1014,7 @@ Inclusion.include = function(objects, include, options, cb) {
}); });
} }
utils.mergeQuery(filter, includeScope, { fields: false }); utils.mergeQuery(filter, includeScope, {fields: false});
related = inst[relationName].bind(inst, filter); related = inst[relationName].bind(inst, filter);
} else { } else {

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
module.exports.buildOneToOneIdentityMapWithOrigKeys = buildOneToOneIdentityMapWithOrigKeys; module.exports.buildOneToOneIdentityMapWithOrigKeys = buildOneToOneIdentityMapWithOrigKeys;
module.exports.buildOneToManyIdentityMapWithOrigKeys = buildOneToManyIdentityMapWithOrigKeys; module.exports.buildOneToManyIdentityMapWithOrigKeys = buildOneToManyIdentityMapWithOrigKeys;
module.exports.join = join; module.exports.join = join;

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
module.exports = function getIntrospector(ModelBuilder) { module.exports = function getIntrospector(ModelBuilder) {
function introspectType(value) { function introspectType(value) {
// Unknown type, using Any // Unknown type, using Any

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var util = require('util'); var util = require('util');
/** /**

View File

@ -18,7 +18,7 @@ module.exports = function keyValueSet(key, value, options, callback) {
callback = options; callback = options;
options = {}; options = {};
} else if (typeof options === 'number') { } else if (typeof options === 'number') {
options = { ttl: options }; options = {ttl: options};
} else if (!options) { } else if (!options) {
options = {}; options = {};
} }

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var util = require('util'); var util = require('util');
var Any = require('./types').Types.Any; var Any = require('./types').Types.Any;

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var debug = require('debug')('loopback:mixin'); var debug = require('debug')('loopback:mixin');
var assert = require('assert'); var assert = require('assert');

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
/*! /*!
* Module dependencies * Module dependencies
@ -73,7 +74,7 @@ function isModelClass(cls) {
ModelBuilder.prototype.getModel = function(name, forceCreate) { ModelBuilder.prototype.getModel = function(name, forceCreate) {
var model = this.models[name]; var model = this.models[name];
if (!model && forceCreate) { if (!model && forceCreate) {
model = this.define(name, {}, { unresolved: true }); model = this.define(name, {}, {unresolved: true});
} }
return model; return model;
}; };
@ -203,7 +204,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Return the unresolved model // Return the unresolved model
if (settings.unresolved) { if (settings.unresolved) {
ModelClass.settings = { unresolved: true }; ModelClass.settings = {unresolved: true};
return ModelClass; return ModelClass;
} }
@ -216,7 +217,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Support both flavors path: 'x' and path: '/x' // Support both flavors path: 'x' and path: '/x'
pathName = '/' + pathName; pathName = '/' + pathName;
} }
hiddenProperty(ModelClass, 'http', { path: pathName }); hiddenProperty(ModelClass, 'http', {path: pathName});
hiddenProperty(ModelClass, 'base', ModelBaseClass); hiddenProperty(ModelClass, 'base', ModelBaseClass);
hiddenProperty(ModelClass, '_observers', {}); hiddenProperty(ModelClass, '_observers', {});
hiddenProperty(ModelClass, '_warned', {}); hiddenProperty(ModelClass, '_warned', {});
@ -283,7 +284,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Add the id property // Add the id property
if (idInjection) { if (idInjection) {
// Set up the id property // Set up the id property
ModelClass.definition.defineProperty('id', { type: Number, id: 1, generated: true }); ModelClass.definition.defineProperty('id', {type: Number, id: 1, generated: true});
} }
idNames = modelDefinition.idNames(); // Reload it after rebuild idNames = modelDefinition.idNames(); // Reload it after rebuild
@ -689,7 +690,7 @@ ModelBuilder.prototype.resolveType = function(type) {
return schemaType; return schemaType;
} else { } else {
// The type cannot be resolved, let's create a place holder // The type cannot be resolved, let's create a place holder
type = this.define(type, {}, { unresolved: true }); type = this.define(type, {}, {unresolved: true});
return type; return type;
} }
} else if (type.constructor.name === 'Object') { } else if (type.constructor.name === 'Object') {
@ -736,7 +737,7 @@ ModelBuilder.prototype.buildModels = function(schemas, createModel) {
{ {
name: this.getSchemaName(), name: this.getSchemaName(),
properties: schemas, properties: schemas,
options: { anonymous: true }, options: {anonymous: true},
}, },
]; ];
} }
@ -763,7 +764,7 @@ ModelBuilder.prototype.buildModels = function(schemas, createModel) {
var targetModel = models[relation.target]; var targetModel = models[relation.target];
if (sourceModel && targetModel) { if (sourceModel && targetModel) {
if (typeof sourceModel[relation.type] === 'function') { if (typeof sourceModel[relation.type] === 'function') {
sourceModel[relation.type](targetModel, { as: relation.as }); sourceModel[relation.type](targetModel, {as: relation.as});
} }
} }
} }

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var assert = require('assert'); var assert = require('assert');
var util = require('util'); var util = require('util');
@ -143,7 +144,7 @@ ModelDefinition.prototype.ids = function() {
if (typeof id !== 'number') { if (typeof id !== 'number') {
id = 1; id = 1;
} }
ids.push({ name: key, id: id, property: props[key] }); ids.push({name: key, id: id, property: props[key]});
} }
ids.sort(function(a, b) { ids.sort(function(a, b) {
return a.id - b.id; return a.id - b.id;

View File

@ -201,7 +201,7 @@ ModelBaseClass.prototype._initProperties = function(data, options) {
var multiple = ctor.relations[p].multiple; var multiple = ctor.relations[p].multiple;
var typeName = multiple ? 'Array' : modelTo.modelName; var typeName = multiple ? 'Array' : modelTo.modelName;
var propType = multiple ? [modelTo] : modelTo; var propType = multiple ? [modelTo] : modelTo;
properties[p] = { name: typeName, type: propType }; properties[p] = {name: typeName, type: propType};
this.setStrict(false); this.setStrict(false);
} }

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var async = require('async'); var async = require('async');
var utils = require('./utils'); var utils = require('./utils');

View File

@ -556,7 +556,7 @@ function lookupModelTo(modelFrom, modelTo, params, singularize) {
* @returns {Object} The normalized parameters * @returns {Object} The normalized parameters
*/ */
function polymorphicParams(params, as) { function polymorphicParams(params, as) {
if (typeof params === 'string') params = { as: params }; if (typeof params === 'string') params = {as: params};
if (typeof params.as !== 'string') params.as = as || 'reference'; // default if (typeof params.as !== 'string') params.as = as || 'reference'; // default
params.foreignKey = params.foreignKey || i8n.camelize(params.as + '_id', true); params.foreignKey = params.foreignKey || i8n.camelize(params.as + '_id', true);
params.discriminator = params.discriminator || i8n.camelize(params.as + '_type', true); params.discriminator = params.discriminator || i8n.camelize(params.as + '_type', true);
@ -608,7 +608,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
fk = polymorphic.foreignKey; fk = polymorphic.foreignKey;
} }
if (!params.through) { if (!params.through) {
modelTo.dataSource.defineProperty(modelTo.modelName, discriminator, { type: 'string', index: true }); modelTo.dataSource.defineProperty(modelTo.modelName, discriminator, {type: 'string', index: true});
} }
} }
@ -1023,7 +1023,7 @@ HasManyThrough.prototype.create = function create(data, options, cb) {
var fk2 = keys[1]; var fk2 = keys[1];
function createRelation(to, next) { function createRelation(to, next) {
var d = {}, q = {}, filter = { where: q }; var d = {}, q = {}, filter = {where: q};
d[fk1] = q[fk1] = modelInstance[definition.keyFrom]; d[fk1] = q[fk1] = modelInstance[definition.keyFrom];
d[fk2] = q[fk2] = to[pk2]; d[fk2] = q[fk2] = to[pk2];
definition.applyProperties(modelInstance, d); definition.applyProperties(modelInstance, d);
@ -1088,7 +1088,7 @@ HasManyThrough.prototype.add = function(acInst, data, options, cb) {
query[fk1] = this.modelInstance[pk1]; query[fk1] = this.modelInstance[pk1];
query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst; query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst;
var filter = { where: query }; var filter = {where: query};
definition.applyScope(this.modelInstance, filter); definition.applyScope(this.modelInstance, filter);
@ -1134,7 +1134,7 @@ HasManyThrough.prototype.exists = function(acInst, options, cb) {
query[fk1] = this.modelInstance[pk1]; query[fk1] = this.modelInstance[pk1];
query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst; query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst;
var filter = { where: query }; var filter = {where: query};
definition.applyScope(this.modelInstance, filter); definition.applyScope(this.modelInstance, filter);
@ -1172,7 +1172,7 @@ HasManyThrough.prototype.remove = function(acInst, options, cb) {
query[fk1] = this.modelInstance[pk1]; query[fk1] = this.modelInstance[pk1];
query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst; query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst;
var filter = { where: query }; var filter = {where: query};
definition.applyScope(this.modelInstance, filter); definition.applyScope(this.modelInstance, filter);
@ -1237,12 +1237,12 @@ RelationDefinition.belongsTo = function(modelFrom, modelTo, params) {
discriminator = polymorphic.discriminator; discriminator = polymorphic.discriminator;
if (polymorphic.idType) { // explicit key type if (polymorphic.idType) { // explicit key type
modelFrom.dataSource.defineProperty(modelFrom.modelName, fk, { type: polymorphic.idType, index: true }); modelFrom.dataSource.defineProperty(modelFrom.modelName, fk, {type: polymorphic.idType, index: true});
} else { // try to use the same foreign key type as modelFrom } else { // try to use the same foreign key type as modelFrom
modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelFrom.modelName, pkName); modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelFrom.modelName, pkName);
} }
modelFrom.dataSource.defineProperty(modelFrom.modelName, discriminator, { type: 'string', index: true }); modelFrom.dataSource.defineProperty(modelFrom.modelName, discriminator, {type: 'string', index: true});
} else { } else {
pkName = params.primaryKey || modelTo.dataSource.idName(modelTo.modelName) || 'id'; pkName = params.primaryKey || modelTo.dataSource.idName(modelTo.modelName) || 'id';
relationName = params.as || i8n.camelize(modelTo.modelName, true); relationName = params.as || i8n.camelize(modelTo.modelName, true);
@ -1459,7 +1459,7 @@ BelongsTo.prototype.related = function(condOrRefresh, options, cb) {
} }
if (cachedValue === undefined || !(cachedValue instanceof ModelBaseClass)) { if (cachedValue === undefined || !(cachedValue instanceof ModelBaseClass)) {
var query = { where: {}}; var query = {where: {}};
query.where[pk] = modelInstance[fk]; query.where[pk] = modelInstance[fk];
if (query.where[pk] === undefined || query.where[pk] === null) { if (query.where[pk] === undefined || query.where[pk] === null) {
@ -1557,7 +1557,7 @@ RelationDefinition.hasAndBelongsToMany = function hasAndBelongsToMany(modelFrom,
modelFrom.dataSource.define(name1); modelFrom.dataSource.define(name1);
} }
var options = { as: params.as, through: params.through }; var options = {as: params.as, through: params.through};
options.properties = params.properties; options.properties = params.properties;
options.scope = params.scope; options.scope = params.scope;
@ -1570,7 +1570,7 @@ RelationDefinition.hasAndBelongsToMany = function hasAndBelongsToMany(modelFrom,
var accessor = params.through.prototype[polymorphic.as]; var accessor = params.through.prototype[polymorphic.as];
if (typeof accessor !== 'function') { // declare once if (typeof accessor !== 'function') { // declare once
// use the name of the polymorphic rel, not modelTo // use the name of the polymorphic rel, not modelTo
params.through.belongsTo(polymorphic.as, { polymorphic: true }); params.through.belongsTo(polymorphic.as, {polymorphic: true});
} }
} else { } else {
params.through.belongsTo(modelFrom); params.through.belongsTo(modelFrom);
@ -1611,7 +1611,7 @@ RelationDefinition.hasOne = function(modelFrom, modelTo, params) {
fk = polymorphic.foreignKey; fk = polymorphic.foreignKey;
discriminator = polymorphic.discriminator; discriminator = polymorphic.discriminator;
if (!params.through) { if (!params.through) {
modelTo.dataSource.defineProperty(modelTo.modelName, discriminator, { type: 'string', index: true }); modelTo.dataSource.defineProperty(modelTo.modelName, discriminator, {type: 'string', index: true});
} }
} }
@ -1703,7 +1703,7 @@ HasOne.prototype.create = function(targetModelData, options, cb) {
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
targetModelData[fk] = modelInstance[pk]; targetModelData[fk] = modelInstance[pk];
var query = { where: {}}; var query = {where: {}};
query.where[fk] = targetModelData[fk]; query.where[fk] = targetModelData[fk];
this.definition.applyScope(modelInstance, query); this.definition.applyScope(modelInstance, query);
@ -1880,7 +1880,7 @@ HasOne.prototype.related = function(condOrRefresh, options, cb) {
self.resetCache(newValue); self.resetCache(newValue);
} else if (typeof cb === 'function') { // acts as async getter } else if (typeof cb === 'function') { // acts as async getter
if (cachedValue === undefined) { if (cachedValue === undefined) {
var query = { where: {}}; var query = {where: {}};
query.where[fk] = modelInstance[pk]; query.where[fk] = modelInstance[pk];
definition.applyScope(modelInstance, query); definition.applyScope(modelInstance, query);
modelTo.findOne(query, options, function(err, inst) { modelTo.findOne(query, options, function(err, inst) {
@ -1965,7 +1965,7 @@ RelationDefinition.embedsOne = function(modelFrom, modelTo, params) {
methods: params.methods, methods: params.methods,
}); });
var opts = { type: modelTo }; var opts = {type: modelTo};
if (params.default === true) { if (params.default === true) {
opts.default = function() { return new modelTo(); }; opts.default = function() { return new modelTo(); };
@ -2392,7 +2392,7 @@ RelationDefinition.embedsMany = function embedsMany(modelFrom, modelTo, params)
this.errors.add(propertyName, 'contains duplicate `' + idName + '`', 'uniqueness'); this.errors.add(propertyName, 'contains duplicate `' + idName + '`', 'uniqueness');
err(false); err(false);
} }
}, { code: 'uniqueness' }); }, {code: 'uniqueness'});
} }
// validate all embedded items // validate all embedded items
@ -2750,7 +2750,7 @@ EmbedsMany.prototype.destroyAll = function(where, options, cb) {
var embeddedList = this.embeddedList(); var embeddedList = this.embeddedList();
if (where && Object.keys(where).length > 0) { if (where && Object.keys(where).length > 0) {
var filter = applyFilter({ where: where }); var filter = applyFilter({where: where});
var reject = function(v) { return !filter(v); }; var reject = function(v) { return !filter(v); };
embeddedList = embeddedList ? embeddedList.filter(reject) : embeddedList; embeddedList = embeddedList ? embeddedList.filter(reject) : embeddedList;
} else { } else {
@ -2941,7 +2941,7 @@ EmbedsMany.prototype.add = function(acInst, data, options, cb) {
query[fk2] = (acInst instanceof belongsTo.modelTo) ? acInst[pk2] : acInst; query[fk2] = (acInst instanceof belongsTo.modelTo) ? acInst[pk2] : acInst;
var filter = { where: query }; var filter = {where: query};
belongsTo.applyScope(modelInstance, filter); belongsTo.applyScope(modelInstance, filter);
@ -2988,7 +2988,7 @@ EmbedsMany.prototype.remove = function(acInst, options, cb) {
query[fk2] = (acInst instanceof belongsTo.modelTo) ? acInst[pk2] : acInst; query[fk2] = (acInst instanceof belongsTo.modelTo) ? acInst[pk2] : acInst;
var filter = { where: query }; var filter = {where: query};
belongsTo.applyScope(modelInstance, filter); belongsTo.applyScope(modelInstance, filter);
@ -3045,7 +3045,7 @@ RelationDefinition.referencesMany = function referencesMany(modelFrom, modelTo,
this.errors.add(relationName, msg, 'uniqueness'); this.errors.add(relationName, msg, 'uniqueness');
err(false); err(false);
} }
}, { code: 'uniqueness' }); }, {code: 'uniqueness'});
var scopeMethods = { var scopeMethods = {
findById: scopeMethod(definition, 'findById'), findById: scopeMethod(definition, 'findById'),
@ -3349,7 +3349,7 @@ ReferencesMany.prototype.add = function(acInst, options, cb) {
if (acInst instanceof modelTo) { if (acInst instanceof modelTo) {
insert(acInst, cb); insert(acInst, cb);
} else { } else {
var filter = { where: {}}; var filter = {where: {}};
filter.where[pk] = acInst; filter.where[pk] = acInst;
definition.applyScope(modelInstance, filter); definition.applyScope(modelInstance, filter);

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
/*! /*!
* Dependencies * Dependencies

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var i8n = require('inflection'); var i8n = require('inflection');
var utils = require('./utils'); var utils = require('./utils');
@ -83,7 +84,7 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres
if (!self.__cachedRelations || self.__cachedRelations[name] === undefined || if (!self.__cachedRelations || self.__cachedRelations[name] === undefined ||
actualRefresh) { actualRefresh) {
// It either doesn't hit the cache or refresh is required // It either doesn't hit the cache or refresh is required
var params = mergeQuery(actualCond, scopeParams, { nestedInclude: true }); var params = mergeQuery(actualCond, scopeParams, {nestedInclude: true});
var targetModel = this.targetModel(receiver); var targetModel = this.targetModel(receiver);
targetModel.find(params, options, function(err, data) { targetModel.find(params, options, function(err, data) {
if (!err && saveOnCache) { if (!err && saveOnCache) {
@ -369,7 +370,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
var targetModel = definition.targetModel(this._receiver); var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {}; var scoped = (this._scope && this._scope.where) || {};
var filter = mergeQuery({ where: scoped }, { where: where || {}}); var filter = mergeQuery({where: scoped}, {where: where || {}});
return targetModel.destroyAll(filter.where, options, cb); return targetModel.destroyAll(filter.where, options, cb);
} }
@ -389,7 +390,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = options || {}; options = options || {};
var targetModel = definition.targetModel(this._receiver); var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {}; var scoped = (this._scope && this._scope.where) || {};
var filter = mergeQuery({ where: scoped }, { where: where || {}}); var filter = mergeQuery({where: scoped}, {where: where || {}});
return targetModel.updateAll(filter.where, data, options, cb); return targetModel.updateAll(filter.where, data, options, cb);
} }
@ -417,7 +418,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
filter = filter || {}; filter = filter || {};
var targetModel = definition.targetModel(this._receiver); var targetModel = definition.targetModel(this._receiver);
var idName = targetModel.definition.idName(); var idName = targetModel.definition.idName();
var query = { where: {}}; var query = {where: {}};
query.where[idName] = id; query.where[idName] = id;
query = mergeQuery(query, filter); query = mergeQuery(query, filter);
return this.findOne(query, options, cb); return this.findOne(query, options, cb);
@ -437,7 +438,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = options || {}; options = options || {};
var targetModel = definition.targetModel(this._receiver); var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {}; var scoped = (this._scope && this._scope.where) || {};
filter = mergeQuery({ where: scoped }, filter || {}); filter = mergeQuery({where: scoped}, filter || {});
return targetModel.findOne(filter, options, cb); return targetModel.findOne(filter, options, cb);
} }
@ -455,7 +456,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
var targetModel = definition.targetModel(this._receiver); var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {}; var scoped = (this._scope && this._scope.where) || {};
var filter = mergeQuery({ where: scoped }, { where: where || {}}); var filter = mergeQuery({where: scoped}, {where: where || {}});
return targetModel.count(filter.where, options, cb); return targetModel.count(filter.where, options, cb);
} }

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var debug = require('debug')('loopback:connector:transaction'); var debug = require('debug')('loopback:connector:transaction');

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var Types = {}; var Types = {};
/** /**

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
exports.safeRequire = safeRequire; exports.safeRequire = safeRequire;
exports.fieldsToArray = fieldsToArray; exports.fieldsToArray = fieldsToArray;
@ -163,7 +164,7 @@ function mergeQuery(base, update, spec) {
if (update.where && Object.keys(update.where).length > 0) { if (update.where && Object.keys(update.where).length > 0) {
if (base.where && Object.keys(base.where).length > 0) { if (base.where && Object.keys(base.where).length > 0) {
base.where = { and: [base.where, update.where] }; base.where = {and: [base.where, update.where]};
} else { } else {
base.where = update.where; base.where = update.where;
} }

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var g = require('strong-globalize')(); var g = require('strong-globalize')();
var util = require('util'); var util = require('util');
var extend = util._extend; var extend = util._extend;
@ -208,7 +210,7 @@ Validatable.validate = getConfigurator('custom');
* @options {Object} Options See below * @options {Object} Options See below
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid". * @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
*/ */
Validatable.validateAsync = getConfigurator('custom', { async: true }); Validatable.validateAsync = getConfigurator('custom', {async: true});
/** /**
* Validate uniqueness. Ensure the value for property is unique in the collection of models. * Validate uniqueness. Ensure the value for property is unique in the collection of models.
@ -232,7 +234,7 @@ Validatable.validateAsync = getConfigurator('custom', { async: true });
* @property {Array.<String>} scopedTo List of properties defining the scope. * @property {Array.<String>} scopedTo List of properties defining the scope.
* @property {String} message Optional error message if property is not valid. Default error message: "is not unique". * @property {String} message Optional error message if property is not valid. Default error message: "is not unique".
*/ */
Validatable.validatesUniquenessOf = getConfigurator('uniqueness', { async: true }); Validatable.validatesUniquenessOf = getConfigurator('uniqueness', {async: true});
// implementation of validators // implementation of validators
@ -345,7 +347,7 @@ function validateUniqueness(attr, conf, err, options, done) {
if (blank(this[attr])) { if (blank(this[attr])) {
return process.nextTick(done); return process.nextTick(done);
} }
var cond = { where: {}}; var cond = {where: {}};
cond.where[attr] = this[attr]; cond.where[attr] = this[attr];
if (conf && conf.scopedTo) { if (conf && conf.scopedTo) {

View File

@ -33,8 +33,8 @@
], ],
"devDependencies": { "devDependencies": {
"async-iterators": "^0.2.2", "async-iterators": "^0.2.2",
"eslint": "^2.5.3", "eslint": "^2.13.1",
"eslint-config-loopback": "^2.0.0", "eslint-config-loopback": "^4.0.0",
"mocha": "^2.1.0", "mocha": "^2.1.0",
"should": "^8.0.2" "should": "^8.0.2"
}, },

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
/* /*
* Describe context objects of operation hooks in comprehensive HTML table. * Describe context objects of operation hooks in comprehensive HTML table.
* Usage: * Usage:
@ -35,55 +37,55 @@ Promise.onPossiblyUnhandledRejection(function(err) {
/* eslint-disable camelcase */ /* eslint-disable camelcase */
var operations = [ var operations = [
function find(ds) { function find(ds) {
return ds.TestModel.find({ where: { id: '1' }}); return ds.TestModel.find({where: {id: '1'}});
}, },
function count(ds) { function count(ds) {
return ds.TestModel.count({ id: ds.existingInstance.id }); return ds.TestModel.count({id: ds.existingInstance.id});
}, },
function create(ds) { function create(ds) {
return ds.TestModel.create({ name: 'created' }); return ds.TestModel.create({name: 'created'});
}, },
function findOrCreate_found(ds) { function findOrCreate_found(ds) {
return ds.TestModel.findOrCreate( return ds.TestModel.findOrCreate(
{ where: { name: ds.existingInstance.name }}, {where: {name: ds.existingInstance.name}},
{ name: ds.existingInstance.name }); {name: ds.existingInstance.name});
}, },
function findOrCreate_create(ds) { function findOrCreate_create(ds) {
return ds.TestModel.findOrCreate( return ds.TestModel.findOrCreate(
{ where: { name: 'new-record' }}, {where: {name: 'new-record'}},
{ name: 'new-record' }); {name: 'new-record'});
}, },
function updateOrCreate_create(ds) { function updateOrCreate_create(ds) {
return ds.TestModel.updateOrCreate({ id: 'not-found', name: 'not found' }); return ds.TestModel.updateOrCreate({id: 'not-found', name: 'not found'});
}, },
function updateOrCreate_update(ds) { function updateOrCreate_update(ds) {
return ds.TestModel.updateOrCreate( return ds.TestModel.updateOrCreate(
{ id: ds.existingInstance.id, name: 'new name' }); {id: ds.existingInstance.id, name: 'new name'});
}, },
function replaceOrCreate_create(ds) { function replaceOrCreate_create(ds) {
return ds.TestModel.replaceOrCreate({ id: 'not-found', name: 'not found' }); return ds.TestModel.replaceOrCreate({id: 'not-found', name: 'not found'});
}, },
function replaceOrCreate_update(ds) { function replaceOrCreate_update(ds) {
return ds.TestModel.replaceOrCreate( return ds.TestModel.replaceOrCreate(
{ id: ds.existingInstance.id, name: 'new name' }); {id: ds.existingInstance.id, name: 'new name'});
}, },
function replaceById(ds) { function replaceById(ds) {
return ds.TestModel.replaceById( return ds.TestModel.replaceById(
ds.existingInstance.id, ds.existingInstance.id,
{ name: 'new name' }); {name: 'new name'});
}, },
function updateAll(ds) { function updateAll(ds) {
return ds.TestModel.updateAll({ name: 'searched' }, { name: 'updated' }); return ds.TestModel.updateAll({name: 'searched'}, {name: 'updated'});
}, },
function prototypeSave(ds) { function prototypeSave(ds) {
@ -92,7 +94,7 @@ var operations = [
}, },
function prototypeUpdateAttributes(ds) { function prototypeUpdateAttributes(ds) {
return ds.existingInstance.updateAttributes({ name: 'changed' }); return ds.existingInstance.updateAttributes({name: 'changed'});
}, },
function prototypeDelete(ds) { function prototypeDelete(ds) {
@ -100,7 +102,7 @@ var operations = [
}, },
function deleteAll(ds) { function deleteAll(ds) {
return ds.TestModel.deleteAll({ name: ds.existingInstance.name }); return ds.TestModel.deleteAll({name: ds.existingInstance.name});
}, },
]; ];
/* eslint-enable camelcase */ /* eslint-enable camelcase */
@ -113,13 +115,13 @@ operations.forEach(function(op) {
p.then(report, function(err) { console.error(err.stack); }); p.then(report, function(err) { console.error(err.stack); });
function createOptimizedDataSource() { function createOptimizedDataSource() {
var ds = new DataSource({ connector: Memory }); var ds = new DataSource({connector: Memory});
ds.name = 'Optimized'; ds.name = 'Optimized';
return ds; return ds;
} }
function createUnoptimizedDataSource() { function createUnoptimizedDataSource() {
var ds = new DataSource({ connector: Memory }); var ds = new DataSource({connector: Memory});
ds.name = 'Unoptimized'; ds.name = 'Unoptimized';
// disable optimized methods // disable optimized methods
@ -133,9 +135,9 @@ function createUnoptimizedDataSource() {
function setupTestModels() { function setupTestModels() {
dataSources.forEach(function setupOnDataSource(ds) { dataSources.forEach(function setupOnDataSource(ds) {
var TestModel = ds.TestModel = ds.createModel('TestModel', { var TestModel = ds.TestModel = ds.createModel('TestModel', {
id: { type: String, id: true, default: uid }, id: {type: String, id: true, default: uid},
name: { type: String, required: true }, name: {type: String, required: true},
extra: { type: String, required: false }, extra: {type: String, required: false},
}); });
}); });
return Promise.resolve(); return Promise.resolve();
@ -172,7 +174,7 @@ function resetStorage(ds) {
}); });
return TestModel.deleteAll() return TestModel.deleteAll()
.then(function() { .then(function() {
return TestModel.create({ name: 'first' }); return TestModel.create({name: 'first'});
}) })
.then(function(instance) { .then(function(instance) {
// Look it up from DB so that default values are retrieved // Look it up from DB so that default values are retrieved
@ -180,7 +182,7 @@ function resetStorage(ds) {
}) })
.then(function(instance) { .then(function(instance) {
ds.existingInstance = instance; ds.existingInstance = instance;
return TestModel.create({ name: 'second' }); return TestModel.create({name: 'second'});
}) })
.then(function() { .then(function() {
HOOK_NAMES.forEach(function(hook) { HOOK_NAMES.forEach(function(hook) {

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var should = require('./init.js'); var should = require('./init.js');

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var ModelBuilder = require('../').ModelBuilder; var ModelBuilder = require('../').ModelBuilder;
var should = require('./init'); var should = require('./init');
@ -11,7 +12,7 @@ describe('async observer', function() {
var TestModel; var TestModel;
beforeEach(function defineTestModel() { beforeEach(function defineTestModel() {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
TestModel = modelBuilder.define('TestModel', { name: String }); TestModel = modelBuilder.define('TestModel', {name: String});
}); });
it('calls registered async observers', function(done) { it('calls registered async observers', function(done) {
@ -303,7 +304,7 @@ describe('async observer', function() {
}); });
it('returns a promise when no callback is provided', function() { it('returns a promise when no callback is provided', function() {
var context = { value: 'a-test-context' }; var context = {value: 'a-test-context'};
var p = TestModel.notifyObserversOf('event', context); var p = TestModel.notifyObserversOf('event', context);
(p !== undefined).should.be.true; (p !== undefined).should.be.true;
return p.then(function(result) { return p.then(function(result) {

View File

@ -4,6 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var async = require('async'); var async = require('async');
var db, User; var db, User;
@ -13,13 +15,13 @@ describe('basic-querying', function() {
before(function(done) { before(function(done) {
db = getSchema(); db = getSchema();
User = db.define('User', { User = db.define('User', {
seq: { type: Number, index: true }, seq: {type: Number, index: true},
name: { type: String, index: true, sort: true }, name: {type: String, index: true, sort: true},
email: { type: String, index: true }, email: {type: String, index: true},
birthday: { type: Date, index: true }, birthday: {type: Date, index: true},
role: { type: String, index: true }, role: {type: String, index: true},
order: { type: Number, index: true, sort: true }, order: {type: Number, index: true, sort: true},
vip: { type: Boolean }, vip: {type: Boolean},
}); });
db.automigrate(done); db.automigrate(done);
@ -68,12 +70,12 @@ describe('basic-querying', function() {
var createdUsers; var createdUsers;
before(function(done) { before(function(done) {
var people = [ var people = [
{ name: 'a', vip: true }, {name: 'a', vip: true},
{ name: 'b' }, {name: 'b'},
{ name: 'c' }, {name: 'c'},
{ name: 'd', vip: true }, {name: 'd', vip: true},
{ name: 'e' }, {name: 'e'},
{ name: 'f' }, {name: 'f'},
]; ];
db.automigrate(['User'], function(err) { db.automigrate(['User'], function(err) {
User.create(people, function(err, users) { User.create(people, function(err, users) {
@ -107,7 +109,7 @@ describe('basic-querying', function() {
createdUsers[1].id, createdUsers[1].id,
createdUsers[2].id, createdUsers[2].id,
createdUsers[3].id], createdUsers[3].id],
{ where: { vip: true }}, function(err, users) { {where: {vip: true}}, function(err, users) {
should.exist(users); should.exist(users);
should.not.exist(err); should.not.exist(err);
var names = users.map(function(u) { var names = users.map(function(u) {
@ -147,7 +149,7 @@ describe('basic-querying', function() {
}); });
it('should query limited collection', function(done) { it('should query limited collection', function(done) {
User.find({ limit: 3 }, function(err, users) { User.find({limit: 3}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(3); users.should.have.lengthOf(3);
@ -156,7 +158,7 @@ describe('basic-querying', function() {
}); });
it('should query collection with skip & limit', function(done) { it('should query collection with skip & limit', function(done) {
User.find({ skip: 1, limit: 4, order: 'seq' }, function(err, users) { User.find({skip: 1, limit: 4, order: 'seq'}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users[0].seq.should.be.eql(1); users[0].seq.should.be.eql(1);
@ -166,7 +168,7 @@ describe('basic-querying', function() {
}); });
it('should query collection with offset & limit', function(done) { it('should query collection with offset & limit', function(done) {
User.find({ offset: 2, limit: 3, order: 'seq' }, function(err, users) { User.find({offset: 2, limit: 3, order: 'seq'}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users[0].seq.should.be.eql(2); users[0].seq.should.be.eql(2);
@ -176,7 +178,7 @@ describe('basic-querying', function() {
}); });
it('should query filtered collection', function(done) { it('should query filtered collection', function(done) {
User.find({ where: { role: 'lead' }}, function(err, users) { User.find({where: {role: 'lead'}}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(2); users.should.have.lengthOf(2);
@ -185,7 +187,7 @@ describe('basic-querying', function() {
}); });
it('should query collection sorted by numeric field', function(done) { it('should query collection sorted by numeric field', function(done) {
User.find({ order: 'order' }, function(err, users) { User.find({order: 'order'}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.forEach(function(u, i) { users.forEach(function(u, i) {
@ -196,7 +198,7 @@ describe('basic-querying', function() {
}); });
it('should query collection desc sorted by numeric field', function(done) { it('should query collection desc sorted by numeric field', function(done) {
User.find({ order: 'order DESC' }, function(err, users) { User.find({order: 'order DESC'}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.forEach(function(u, i) { users.forEach(function(u, i) {
@ -207,7 +209,7 @@ describe('basic-querying', function() {
}); });
it('should query collection sorted by string field', function(done) { it('should query collection sorted by string field', function(done) {
User.find({ order: 'name' }, function(err, users) { User.find({order: 'name'}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.shift().name.should.equal('George Harrison'); users.shift().name.should.equal('George Harrison');
@ -218,7 +220,7 @@ describe('basic-querying', function() {
}); });
it('should query collection desc sorted by string field', function(done) { it('should query collection desc sorted by string field', function(done) {
User.find({ order: 'name DESC' }, function(err, users) { User.find({order: 'name DESC'}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.pop().name.should.equal('George Harrison'); users.pop().name.should.equal('George Harrison');
@ -230,7 +232,7 @@ describe('basic-querying', function() {
it('should query sorted desc by order integer field even though there' + it('should query sorted desc by order integer field even though there' +
'is an async model loaded hook', function(done) { 'is an async model loaded hook', function(done) {
User.find({ order: 'order DESC' }, function(err, users) { User.find({order: 'order DESC'}, function(err, users) {
if (err) return done(err); if (err) return done(err);
should.exists(users); should.exists(users);
@ -241,10 +243,10 @@ describe('basic-querying', function() {
}); });
it('should support "and" operator that is satisfied', function(done) { it('should support "and" operator that is satisfied', function(done) {
User.find({ where: { and: [ User.find({where: {and: [
{ name: 'John Lennon' }, {name: 'John Lennon'},
{ role: 'lead' }, {role: 'lead'},
] }}, function(err, users) { ]}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 1); users.should.have.property('length', 1);
done(); done();
@ -252,10 +254,10 @@ describe('basic-querying', function() {
}); });
it('should support "and" operator that is not satisfied', function(done) { it('should support "and" operator that is not satisfied', function(done) {
User.find({ where: { and: [ User.find({where: {and: [
{ name: 'John Lennon' }, {name: 'John Lennon'},
{ role: 'member' }, {role: 'member'},
] }}, function(err, users) { ]}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
done(); done();
@ -263,10 +265,10 @@ describe('basic-querying', function() {
}); });
it('should support "or" that is satisfied', function(done) { it('should support "or" that is satisfied', function(done) {
User.find({ where: { or: [ User.find({where: {or: [
{ name: 'John Lennon' }, {name: 'John Lennon'},
{ role: 'lead' }, {role: 'lead'},
] }}, function(err, users) { ]}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 2); users.should.have.property('length', 2);
done(); done();
@ -274,10 +276,10 @@ describe('basic-querying', function() {
}); });
it('should support "or" operator that is not satisfied', function(done) { it('should support "or" operator that is not satisfied', function(done) {
User.find({ where: { or: [ User.find({where: {or: [
{ name: 'XYZ' }, {name: 'XYZ'},
{ role: 'Hello1' }, {role: 'Hello1'},
] }}, function(err, users) { ]}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
done(); done();
@ -285,7 +287,7 @@ describe('basic-querying', function() {
}); });
it('should support date "gte" that is satisfied', function(done) { it('should support date "gte" that is satisfied', function(done) {
User.find({ order: 'seq', where: { birthday: { 'gte': new Date('1980-12-08') }, User.find({order: 'seq', where: {birthday: {'gte': new Date('1980-12-08')},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 1); users.should.have.property('length', 1);
@ -295,7 +297,7 @@ describe('basic-querying', function() {
}); });
it('should support date "gt" that is not satisfied', function(done) { it('should support date "gt" that is not satisfied', function(done) {
User.find({ order: 'seq', where: { birthday: { 'gt': new Date('1980-12-08') }, User.find({order: 'seq', where: {birthday: {'gt': new Date('1980-12-08')},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
@ -304,7 +306,7 @@ describe('basic-querying', function() {
}); });
it('should support date "gt" that is satisfied', function(done) { it('should support date "gt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { birthday: { 'gt': new Date('1980-12-07') }, User.find({order: 'seq', where: {birthday: {'gt': new Date('1980-12-07')},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 1); users.should.have.property('length', 1);
@ -314,7 +316,7 @@ describe('basic-querying', function() {
}); });
it('should support date "lt" that is satisfied', function(done) { it('should support date "lt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { birthday: { 'lt': new Date('1980-12-07') }, User.find({order: 'seq', where: {birthday: {'lt': new Date('1980-12-07')},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 1); users.should.have.property('length', 1);
@ -324,7 +326,7 @@ describe('basic-querying', function() {
}); });
it('should support number "gte" that is satisfied', function(done) { it('should support number "gte" that is satisfied', function(done) {
User.find({ order: 'seq', where: { order: { 'gte': 3 }, User.find({order: 'seq', where: {order: {'gte': 3},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 4); users.should.have.property('length', 4);
@ -334,7 +336,7 @@ describe('basic-querying', function() {
}); });
it('should support number "gt" that is not satisfied', function(done) { it('should support number "gt" that is not satisfied', function(done) {
User.find({ order: 'seq', where: { order: { 'gt': 6 }, User.find({order: 'seq', where: {order: {'gt': 6},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
@ -343,7 +345,7 @@ describe('basic-querying', function() {
}); });
it('should support number "gt" that is satisfied', function(done) { it('should support number "gt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { order: { 'gt': 5 }, User.find({order: 'seq', where: {order: {'gt': 5},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 1); users.should.have.property('length', 1);
@ -353,7 +355,7 @@ describe('basic-querying', function() {
}); });
it('should support number "lt" that is satisfied', function(done) { it('should support number "lt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { order: { 'lt': 2 }, User.find({order: 'seq', where: {order: {'lt': 2},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 1); users.should.have.property('length', 1);
@ -363,7 +365,7 @@ describe('basic-querying', function() {
}); });
it('should support number "gt" that is satisfied by null value', function(done) { it('should support number "gt" that is satisfied by null value', function(done) {
User.find({ order: 'seq', where: { order: { 'gt': null }, User.find({order: 'seq', where: {order: {'gt': null},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
@ -372,7 +374,7 @@ describe('basic-querying', function() {
}); });
it('should support number "lt" that is not satisfied by null value', function(done) { it('should support number "lt" that is not satisfied by null value', function(done) {
User.find({ order: 'seq', where: { order: { 'lt': null }, User.find({order: 'seq', where: {order: {'lt': null},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
@ -381,7 +383,7 @@ describe('basic-querying', function() {
}); });
it('should support string "gte" that is satisfied by null value', function(done) { it('should support string "gte" that is satisfied by null value', function(done) {
User.find({ order: 'seq', where: { name: { 'gte': null }, User.find({order: 'seq', where: {name: {'gte': null},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
@ -390,7 +392,7 @@ describe('basic-querying', function() {
}); });
it('should support string "gte" that is satisfied', function(done) { it('should support string "gte" that is satisfied', function(done) {
User.find({ order: 'seq', where: { name: { 'gte': 'Paul McCartney' }, User.find({order: 'seq', where: {name: {'gte': 'Paul McCartney'},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 4); users.should.have.property('length', 4);
@ -400,7 +402,7 @@ describe('basic-querying', function() {
}); });
it('should support string "gt" that is not satisfied', function(done) { it('should support string "gt" that is not satisfied', function(done) {
User.find({ order: 'seq', where: { name: { 'gt': 'xyz' }, User.find({order: 'seq', where: {name: {'gt': 'xyz'},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
@ -409,7 +411,7 @@ describe('basic-querying', function() {
}); });
it('should support string "gt" that is satisfied', function(done) { it('should support string "gt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { name: { 'gt': 'Paul McCartney' }, User.find({order: 'seq', where: {name: {'gt': 'Paul McCartney'},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 3); users.should.have.property('length', 3);
@ -419,7 +421,7 @@ describe('basic-querying', function() {
}); });
it('should support string "lt" that is satisfied', function(done) { it('should support string "lt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { name: { 'lt': 'Paul McCartney' }, User.find({order: 'seq', where: {name: {'lt': 'Paul McCartney'},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 2); users.should.have.property('length', 2);
@ -429,7 +431,7 @@ describe('basic-querying', function() {
}); });
it('should support boolean "gte" that is satisfied', function(done) { it('should support boolean "gte" that is satisfied', function(done) {
User.find({ order: 'seq', where: { vip: { 'gte': true }, User.find({order: 'seq', where: {vip: {'gte': true},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 3); users.should.have.property('length', 3);
@ -439,7 +441,7 @@ describe('basic-querying', function() {
}); });
it('should support boolean "gt" that is not satisfied', function(done) { it('should support boolean "gt" that is not satisfied', function(done) {
User.find({ order: 'seq', where: { vip: { 'gt': true }, User.find({order: 'seq', where: {vip: {'gt': true},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 0); users.should.have.property('length', 0);
@ -448,7 +450,7 @@ describe('basic-querying', function() {
}); });
it('should support boolean "gt" that is satisfied', function(done) { it('should support boolean "gt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { vip: { 'gt': false }, User.find({order: 'seq', where: {vip: {'gt': false},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 3); users.should.have.property('length', 3);
@ -458,7 +460,7 @@ describe('basic-querying', function() {
}); });
it('should support boolean "lt" that is satisfied', function(done) { it('should support boolean "lt" that is satisfied', function(done) {
User.find({ order: 'seq', where: { vip: { 'lt': true }, User.find({order: 'seq', where: {vip: {'lt': true},
}}, function(err, users) { }}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.should.have.property('length', 2); users.should.have.property('length', 2);
@ -475,7 +477,7 @@ describe('basic-querying', function() {
return { return {
expect: function(arr) { expect: function(arr) {
remaining++; remaining++;
User.find({ fields: fields }, function(err, users) { User.find({fields: fields}, function(err, users) {
remaining--; remaining--;
if (err) return done(err); if (err) return done(err);
@ -505,10 +507,10 @@ describe('basic-querying', function() {
}; };
} }
sample({ name: true }).expect(['name']); sample({name: true}).expect(['name']);
sample({ name: false }).expect(['id', 'seq', 'email', 'role', 'order', 'birthday', 'vip']); sample({name: false}).expect(['id', 'seq', 'email', 'role', 'order', 'birthday', 'vip']);
sample({ name: false, id: true }).expect(['id']); sample({name: false, id: true}).expect(['id']);
sample({ id: true }).expect(['id']); sample({id: true}).expect(['id']);
sample('id').expect(['id']); sample('id').expect(['id']);
sample(['id']).expect(['id']); sample(['id']).expect(['id']);
sample(['email']).expect(['email']); sample(['email']).expect(['email']);
@ -530,7 +532,7 @@ describe('basic-querying', function() {
}); });
it('should query filtered count', function(done) { it('should query filtered count', function(done) {
User.count({ role: 'lead' }, function(err, n) { User.count({role: 'lead'}, function(err, n) {
should.not.exist(err); should.not.exist(err);
should.exist(n); should.exist(n);
n.should.equal(2); n.should.equal(2);
@ -544,7 +546,7 @@ describe('basic-querying', function() {
before(seed); before(seed);
it('should find first record (default sort by id)', function(done) { it('should find first record (default sort by id)', function(done) {
User.all({ order: 'id' }, function(err, users) { User.all({order: 'id'}, function(err, users) {
User.findOne(function(e, u) { User.findOne(function(e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
@ -555,7 +557,7 @@ describe('basic-querying', function() {
}); });
it('should find first record', function(done) { it('should find first record', function(done) {
User.findOne({ order: 'order' }, function(e, u) { User.findOne({order: 'order'}, function(e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(1); u.order.should.equal(1);
@ -565,7 +567,7 @@ describe('basic-querying', function() {
}); });
it('should find last record', function(done) { it('should find last record', function(done) {
User.findOne({ order: 'order DESC' }, function(e, u) { User.findOne({order: 'order DESC'}, function(e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(6); u.order.should.equal(6);
@ -576,7 +578,7 @@ describe('basic-querying', function() {
it('should find last record in filtered set', function(done) { it('should find last record in filtered set', function(done) {
User.findOne({ User.findOne({
where: { role: 'lead' }, where: {role: 'lead'},
order: 'order DESC', order: 'order DESC',
}, function(e, u) { }, function(e, u) {
should.not.exist(e); should.not.exist(e);
@ -589,7 +591,7 @@ describe('basic-querying', function() {
it('should work even when find by id', function(done) { it('should work even when find by id', function(done) {
User.findOne(function(e, u) { User.findOne(function(e, u) {
User.findOne({ where: { id: u.id }}, function(err, user) { User.findOne({where: {id: u.id}}, function(err, user) {
should.not.exist(err); should.not.exist(err);
should.exist(user); should.exist(user);
done(); done();
@ -634,7 +636,7 @@ describe('basic-querying', function() {
// `undefined` is not tested because the `removeUndefined` function // `undefined` is not tested because the `removeUndefined` function
// in `lib/dao.js` removes it before coercion // in `lib/dao.js` removes it before coercion
invalidDataTypes.forEach(function(invalidDataType) { invalidDataTypes.forEach(function(invalidDataType) {
User.find({ where: { name: { regexp: invalidDataType }}}, function(err, User.find({where: {name: {regexp: invalidDataType}}}, function(err,
users) { users) {
should.exist(err); should.exist(err);
}); });
@ -651,7 +653,7 @@ describe.skip('queries', function() {
var db = getSchema(); var db = getSchema();
Todo = db.define('Todo', { Todo = db.define('Todo', {
id: false, id: false,
content: { type: 'string' }, content: {type: 'string'},
}, { }, {
idInjection: false, idInjection: false,
}); });
@ -660,16 +662,16 @@ describe.skip('queries', function() {
beforeEach(function resetFixtures(done) { beforeEach(function resetFixtures(done) {
Todo.destroyAll(function() { Todo.destroyAll(function() {
Todo.create([ Todo.create([
{ content: 'Buy eggs' }, {content: 'Buy eggs'},
{ content: 'Buy milk' }, {content: 'Buy milk'},
{ content: 'Buy sausages' }, {content: 'Buy sausages'},
], done); ], done);
}); });
}); });
context('that do not require an id', function() { context('that do not require an id', function() {
it('should work for create', function(done) { it('should work for create', function(done) {
Todo.create({ content: 'Buy ham' }, function(err) { Todo.create({content: 'Buy ham'}, function(err) {
should.not.exist(err); should.not.exist(err);
done(); done();
}); });
@ -678,7 +680,7 @@ describe.skip('queries', function() {
it('should work for updateOrCreate/upsert', function(done) { it('should work for updateOrCreate/upsert', function(done) {
var aliases = ['updateOrCreate', 'upsert']; var aliases = ['updateOrCreate', 'upsert'];
async.each(aliases, function(alias, cb) { async.each(aliases, function(alias, cb) {
Todo[alias]({ content: 'Buy ham' }, function(err) { Todo[alias]({content: 'Buy ham'}, function(err) {
should.not.exist(err); should.not.exist(err);
cb(); cb();
}); });
@ -686,14 +688,14 @@ describe.skip('queries', function() {
}); });
it('should work for findOrCreate', function(done) { it('should work for findOrCreate', function(done) {
Todo.findOrCreate({ content: 'Buy ham' }, function(err) { Todo.findOrCreate({content: 'Buy ham'}, function(err) {
should.not.exist(err); should.not.exist(err);
done(); done();
}); });
}); });
it('should work for exists', function(done) { it('should work for exists', function(done) {
Todo.exists({ content: 'Buy ham' }, function(err) { Todo.exists({content: 'Buy ham'}, function(err) {
should.not.exist(err); should.not.exist(err);
done(); done();
}); });
@ -726,14 +728,14 @@ describe.skip('queries', function() {
}); });
it('should work for update/updateAll', function(done) { it('should work for update/updateAll', function(done) {
Todo.update({ content: 'Buy ham' }, function(err) { Todo.update({content: 'Buy ham'}, function(err) {
should.not.exist(err); should.not.exist(err);
done(); done();
}); });
}); });
it('should work for count', function(done) { it('should work for count', function(done) {
Todo.count({ content: 'Buy eggs' }, function(err) { Todo.count({content: 'Buy eggs'}, function(err) {
should.not.exist(err); should.not.exist(err);
done(); done();
}); });
@ -803,7 +805,7 @@ describe.skip('queries', function() {
it('should return an error for instance.updateAttributes', function(done) { it('should return an error for instance.updateAttributes', function(done) {
Todo.findOne(function(err, todo) { Todo.findOne(function(err, todo) {
todo.updateAttributes({ content: 'Buy ham' }, function(err) { todo.updateAttributes({content: 'Buy ham'}, function(err) {
should.exist(err); should.exist(err);
err.message.should.equal(expectedErrMsg); err.message.should.equal(expectedErrMsg);
done(); done();
@ -833,10 +835,10 @@ function seed(done) {
order: 1, order: 1,
vip: true, vip: true,
}, },
{ seq: 2, name: 'George Harrison', order: 5, vip: false }, {seq: 2, name: 'George Harrison', order: 5, vip: false},
{ seq: 3, name: 'Ringo Starr', order: 6, vip: false }, {seq: 3, name: 'Ringo Starr', order: 6, vip: false},
{ seq: 4, name: 'Pete Best', order: 4 }, {seq: 4, name: 'Pete Best', order: 4},
{ seq: 5, name: 'Stuart Sutcliffe', order: 3, vip: true }, {seq: 5, name: 'Stuart Sutcliffe', order: 3, vip: true},
]; ];
async.series([ async.series([

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
require('./datatype.test.js'); require('./datatype.test.js');
require('./basic-querying.test.js'); require('./basic-querying.test.js');
require('./manipulation.test.js'); require('./manipulation.test.js');

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var Schema = require('../index').Schema; var Schema = require('../index').Schema;
var Text = Schema.Text; var Text = Schema.Text;
@ -98,45 +100,45 @@ function testOrm(dataSource) {
it('should define class', function(test) { it('should define class', function(test) {
User = dataSource.define('User', { User = dataSource.define('User', {
name: { type: String, index: true }, name: {type: String, index: true},
email: { type: String, index: true }, email: {type: String, index: true},
bio: Text, bio: Text,
approved: Boolean, approved: Boolean,
joinedAt: Date, joinedAt: Date,
age: Number, age: Number,
passwd: { type: String, index: true }, passwd: {type: String, index: true},
}); });
Dog = dataSource.define('Dog', { Dog = dataSource.define('Dog', {
name: { type: String, limit: 64, allowNull: false }, name: {type: String, limit: 64, allowNull: false},
}); });
Log = dataSource.define('Log', { Log = dataSource.define('Log', {
ownerId: { type: Number, allowNull: true }, ownerId: {type: Number, allowNull: true},
name: { type: String, limit: 64, allowNull: false }, name: {type: String, limit: 64, allowNull: false},
}); });
Log.belongsTo(Dog, { as: 'owner', foreignKey: 'ownerId' }); Log.belongsTo(Dog, {as: 'owner', foreignKey: 'ownerId'});
dataSource.extendModel('User', { dataSource.extendModel('User', {
settings: { type: Schema.JSON }, settings: {type: Schema.JSON},
extra: Object, extra: Object,
}); });
var newuser = new User({ settings: { hey: 'you' }}); var newuser = new User({settings: {hey: 'you'}});
test.ok(newuser.settings); test.ok(newuser.settings);
Post = dataSource.define('Post', { Post = dataSource.define('Post', {
title: { type: String, length: 255, index: true }, title: {type: String, length: 255, index: true},
subject: { type: String }, subject: {type: String},
content: { type: Text }, content: {type: Text},
date: { type: Date, default: function() { date: {type: Date, default: function() {
return new Date; return new Date;
}, index: true }, }, index: true},
published: { type: Boolean, default: false, index: true }, published: {type: Boolean, default: false, index: true},
likes: [], likes: [],
related: [RelatedPost], related: [RelatedPost],
}, { table: 'posts' }); }, {table: 'posts'});
function RelatedPost() { function RelatedPost() {
} }
@ -149,7 +151,7 @@ function testOrm(dataSource) {
process.nextTick(done); process.nextTick(done);
}); });
User.hasMany(Post, { as: 'posts', foreignKey: 'userId' }); User.hasMany(Post, {as: 'posts', foreignKey: 'userId'});
// creates instance methods: // creates instance methods:
// user.posts(conds) // user.posts(conds)
// user.posts.build(data) // like new Post({userId: user.id}); // user.posts.build(data) // like new Post({userId: user.id});
@ -164,7 +166,7 @@ function testOrm(dataSource) {
// user.latestPost.build(data) // user.latestPost.build(data)
// user.latestPost.create(data) // user.latestPost.create(data)
Post.belongsTo(User, { as: 'author', foreignKey: 'userId' }); Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
// creates instance methods: // creates instance methods:
// post.author(callback) -- getter when called with function // post.author(callback) -- getter when called with function
// post.author() -- sync getter when called without params // post.author() -- sync getter when called without params
@ -174,8 +176,8 @@ function testOrm(dataSource) {
number: String, number: String,
}); });
Passport.belongsTo(User, { as: 'owner', foreignKey: 'ownerId' }); Passport.belongsTo(User, {as: 'owner', foreignKey: 'ownerId'});
User.hasMany(Passport, { as: 'passports', foreignKey: 'ownerId' }); User.hasMany(Passport, {as: 'passports', foreignKey: 'ownerId'});
var user = new User; var user = new User;
@ -202,8 +204,8 @@ function testOrm(dataSource) {
it('should initialize object properly', function(test) { it('should initialize object properly', function(test) {
var hw = 'Hello word', var hw = 'Hello word',
now = Date.now(), now = Date.now(),
post = new Post({ title: hw }), post = new Post({title: hw}),
anotherPost = Post({ title: 'Resig style constructor' }); anotherPost = Post({title: 'Resig style constructor'});
test.equal(post.title, hw); test.equal(post.title, hw);
test.ok(!post.propertyChanged('title'), 'property changed: title'); test.ok(!post.propertyChanged('title'), 'property changed: title');
@ -235,7 +237,7 @@ function testOrm(dataSource) {
test.equal(obj.title, title2); test.equal(obj.title, title2);
test.ok(!obj.propertyChanged('title')); test.ok(!obj.propertyChanged('title'));
var p = new Post({ title: 1 }); var p = new Post({title: 1});
p.title = 2; p.title = 2;
p.save(function(err, obj) { p.save(function(err, obj) {
test.ok(!p.propertyChanged('title')); test.ok(!p.propertyChanged('title'));
@ -272,7 +274,7 @@ function testOrm(dataSource) {
}); });
it('should save only dataSource-defined field in database', function(test) { it('should save only dataSource-defined field in database', function(test) {
Post.create({ title: '1602', nonSchemaField: 'some value' }, function(err, post) { Post.create({title: '1602', nonSchemaField: 'some value'}, function(err, post) {
test.ok(!post.nonSchemaField); test.ok(!post.nonSchemaField);
post.a = 1; post.a = 1;
post.save(function() { post.save(function() {
@ -303,7 +305,7 @@ function testOrm(dataSource) {
it('should not re-instantiate object on saving', function(test) { it('should not re-instantiate object on saving', function(test) {
var title = 'Initial title'; var title = 'Initial title';
var post = new Post({ title: title }); var post = new Post({title: title});
post.save(function(err, savedPost) { post.save(function(err, savedPost) {
test.strictEqual(post, savedPost); test.strictEqual(post, savedPost);
test.done(); test.done();
@ -363,7 +365,7 @@ function testOrm(dataSource) {
// }); // });
it('should update single attribute', function(test) { it('should update single attribute', function(test) {
Post.create({ title: 'title', content: 'content', published: true }, function(err, post) { Post.create({title: 'title', content: 'content', published: true}, function(err, post) {
post.content = 'New content'; post.content = 'New content';
post.updateAttribute('title', 'New title', function() { post.updateAttribute('title', 'New title', function() {
test.equal(post.title, 'New title'); test.equal(post.title, 'New title');
@ -396,8 +398,8 @@ function testOrm(dataSource) {
it('should find records filtered with multiple attributes', function(test) { it('should find records filtered with multiple attributes', function(test) {
var d = new Date; var d = new Date;
Post.create({ title: 'title', content: 'content', published: true, date: d }, function(err, post) { Post.create({title: 'title', content: 'content', published: true, date: d}, function(err, post) {
Post.all({ where: { title: 'title', date: d, published: true }}, function(err, res) { Post.all({where: {title: 'title', date: d, published: true}}, function(err, res) {
test.equals(res.length, 1, 'Filtering Posts returns one post'); test.equals(res.length, 1, 'Filtering Posts returns one post');
test.done(); test.done();
}); });
@ -445,9 +447,9 @@ function testOrm(dataSource) {
it('should navigate variations of belongsTo regardless of column name', function(test) { it('should navigate variations of belongsTo regardless of column name', function(test) {
Dog.create({ name: 'theDog' }, function(err, obj) { Dog.create({name: 'theDog'}, function(err, obj) {
test.ok(obj instanceof Dog); test.ok(obj instanceof Dog);
Log.create({ name: 'theLog', ownerId: obj.id }, function(err, obj) { Log.create({name: 'theLog', ownerId: obj.id}, function(err, obj) {
test.ok(obj instanceof Log); test.ok(obj instanceof Log);
obj.owner(function(err, obj) { obj.owner(function(err, obj) {
test.ok(!err, 'Should not have an error.'); // Before cba174b this would be 'Error: Permission denied' test.ok(!err, 'Should not have an error.'); // Before cba174b this would be 'Error: Permission denied'
@ -472,7 +474,7 @@ function testOrm(dataSource) {
User.create(function(e, u) { User.create(function(e, u) {
u.posts.create({}, function(e, p) { u.posts.create({}, function(e, p) {
u.posts({ where: { id: p.id }}, function(e, posts) { u.posts({where: {id: p.id}}, function(e, posts) {
test.equal(posts.length, 1, 'There should be only 1 post.'); test.equal(posts.length, 1, 'There should be only 1 post.');
test.done(); test.done();
}); });
@ -495,7 +497,7 @@ function testOrm(dataSource) {
// We could get the user with belongs to relationship but it is better if there is no interactions. // We could get the user with belongs to relationship but it is better if there is no interactions.
User.findById(post.userId, function(err, user) { User.findById(post.userId, function(err, user) {
User.create(function(err, voidUser) { User.create(function(err, voidUser) {
Post.create({ userId: user.id }, function() { Post.create({userId: user.id}, function() {
// There can't be any concurrency because we are counting requests // There can't be any concurrency because we are counting requests
// We are first testing cases when user has posts // We are first testing cases when user has posts
@ -509,7 +511,7 @@ function testOrm(dataSource) {
if (dataSource.name === 'mongodb') { // for the moment mongodb doesn\'t support additional conditions on hasMany relations (see above) if (dataSource.name === 'mongodb') { // for the moment mongodb doesn\'t support additional conditions on hasMany relations (see above)
test.done(); test.done();
} else { } else {
user.posts({ where: { id: data[0].id }}, function(err, data) { user.posts({where: {id: data[0].id}}, function(err, data) {
test.equal(data.length, 1, 'There should be only one post.'); test.equal(data.length, 1, 'There should be only one post.');
requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should be one additional request since we added conditions.'); requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should be one additional request since we added conditions.');
@ -561,7 +563,7 @@ function testOrm(dataSource) {
var wait = 2; var wait = 2;
test.ok(Post.scope, 'Scope supported'); test.ok(Post.scope, 'Scope supported');
Post.scope('published', { where: { published: true }}); Post.scope('published', {where: {published: true}});
test.ok(typeof Post.published === 'function'); test.ok(typeof Post.published === 'function');
test.ok(Post.published._scope.where.published === true); test.ok(Post.published._scope.where.published === true);
var post = Post.published.build(); var post = Post.published.build();
@ -599,12 +601,12 @@ function testOrm(dataSource) {
it('should handle ORDER clause', function(test) { it('should handle ORDER clause', function(test) {
var titles = [ var titles = [
{ title: 'Title A', subject: 'B' }, {title: 'Title A', subject: 'B'},
{ title: 'Title Z', subject: 'A' }, {title: 'Title Z', subject: 'A'},
{ title: 'Title M', subject: 'C' }, {title: 'Title M', subject: 'C'},
{ title: 'Title A', subject: 'A' }, {title: 'Title A', subject: 'A'},
{ title: 'Title B', subject: 'A' }, {title: 'Title B', subject: 'A'},
{ title: 'Title C', subject: 'D' }, {title: 'Title C', subject: 'D'},
]; ];
var isRedis = Post.dataSource.name === 'redis'; var isRedis = Post.dataSource.name === 'redis';
var dates = isRedis ? [5, 9, 0, 17, 10, 9] : [ var dates = isRedis ? [5, 9, 0, 17, 10, 9] : [
@ -616,7 +618,7 @@ function testOrm(dataSource) {
new Date(1000 * 9), new Date(1000 * 9),
]; ];
titles.forEach(function(t, i) { titles.forEach(function(t, i) {
Post.create({ title: t.title, subject: t.subject, date: dates[i] }, done); Post.create({title: t.title, subject: t.subject, date: dates[i]}, done);
}); });
var i = 0, tests = 0; var i = 0, tests = 0;
@ -645,7 +647,7 @@ function testOrm(dataSource) {
function doStringTest() { function doStringTest() {
tests += 1; tests += 1;
Post.all({ order: 'title' }, function(err, posts) { Post.all({order: 'title'}, function(err, posts) {
if (err) console.log(err); if (err) console.log(err);
test.equal(posts.length, 6); test.equal(posts.length, 6);
titles.sort(compare).forEach(function(t, i) { titles.sort(compare).forEach(function(t, i) {
@ -657,7 +659,7 @@ function testOrm(dataSource) {
function doNumberTest() { function doNumberTest() {
tests += 1; tests += 1;
Post.all({ order: 'date' }, function(err, posts) { Post.all({order: 'date'}, function(err, posts) {
if (err) console.log(err); if (err) console.log(err);
test.equal(posts.length, 6); test.equal(posts.length, 6);
dates.sort(numerically).forEach(function(d, i) { dates.sort(numerically).forEach(function(d, i) {
@ -670,7 +672,7 @@ function testOrm(dataSource) {
function doFilterAndSortTest() { function doFilterAndSortTest() {
tests += 1; tests += 1;
Post.all({ where: { date: new Date(1000 * 9) }, order: 'title', limit: 3 }, function(err, posts) { Post.all({where: {date: new Date(1000 * 9)}, order: 'title', limit: 3}, function(err, posts) {
if (err) console.log(err); if (err) console.log(err);
console.log(posts.length); console.log(posts.length);
test.equal(posts.length, 2, 'Exactly 2 posts returned by query'); test.equal(posts.length, 2, 'Exactly 2 posts returned by query');
@ -685,7 +687,7 @@ function testOrm(dataSource) {
function doFilterAndSortReverseTest() { function doFilterAndSortReverseTest() {
tests += 1; tests += 1;
Post.all({ where: { date: new Date(1000 * 9) }, order: 'title DESC', limit: 3 }, function(err, posts) { Post.all({where: {date: new Date(1000 * 9)}, order: 'title DESC', limit: 3}, function(err, posts) {
if (err) console.log(err); if (err) console.log(err);
test.equal(posts.length, 2, 'Exactly 2 posts returned by query'); test.equal(posts.length, 2, 'Exactly 2 posts returned by query');
['Title Z', 'Title C'].forEach(function(t, i) { ['Title Z', 'Title C'].forEach(function(t, i) {
@ -699,7 +701,7 @@ function testOrm(dataSource) {
function doMultipleSortTest() { function doMultipleSortTest() {
tests += 1; tests += 1;
Post.all({ order: 'title ASC, subject ASC' }, function(err, posts) { Post.all({order: 'title ASC, subject ASC'}, function(err, posts) {
if (err) console.log(err); if (err) console.log(err);
test.equal(posts.length, 6); test.equal(posts.length, 6);
test.equal(posts[0].title, 'Title A'); test.equal(posts[0].title, 'Title A');
@ -713,7 +715,7 @@ function testOrm(dataSource) {
function doMultipleReverseSortTest() { function doMultipleReverseSortTest() {
tests += 1; tests += 1;
Post.all({ order: 'title ASC, subject DESC' }, function(err, posts) { Post.all({order: 'title ASC, subject DESC'}, function(err, posts) {
if (err) console.log(err); if (err) console.log(err);
test.equal(posts.length, 6); test.equal(posts.length, 6);
test.equal(posts[0].title, 'Title A'); test.equal(posts[0].title, 'Title A');
@ -893,7 +895,7 @@ function testOrm(dataSource) {
User.destroyAll(function() { User.destroyAll(function() {
emails.forEach(function(email) { emails.forEach(function(email) {
wait += 1; wait += 1;
User.create({ email: email, name: 'Nick' }, done); User.create({email: email, name: 'Nick'}, done);
}); });
}); });
var tests = 2; var tests = 2;
@ -908,7 +910,7 @@ function testOrm(dataSource) {
} }
function doSortTest() { function doSortTest() {
User.all({ order: 'email ASC', where: { name: 'Nick' }}, function(err, users) { User.all({order: 'email ASC', where: {name: 'Nick'}}, function(err, users) {
var _emails = emails.sort(); var _emails = emails.sort();
users.forEach(function(user, i) { users.forEach(function(user, i) {
test.equal(_emails[i], user.email, 'ASC sorting'); test.equal(_emails[i], user.email, 'ASC sorting');
@ -918,7 +920,7 @@ function testOrm(dataSource) {
} }
function doReverseSortTest() { function doReverseSortTest() {
User.all({ order: 'email DESC', where: { name: 'Nick' }}, function(err, users) { User.all({order: 'email DESC', where: {name: 'Nick'}}, function(err, users) {
var _emails = emails.sort().reverse(); var _emails = emails.sort().reverse();
users.forEach(function(user, i) { users.forEach(function(user, i) {
test.equal(_emails[i], user.email, 'DESC sorting'); test.equal(_emails[i], user.email, 'DESC sorting');
@ -936,7 +938,7 @@ function testOrm(dataSource) {
Post.create(function(err, post) { Post.create(function(err, post) {
var id = post.id; var id = post.id;
test.ok(post.published === false); test.ok(post.published === false);
post.updateAttributes({ title: 'hey', published: true }, function() { post.updateAttributes({title: 'hey', published: true}, function() {
Post.find(id, function(err, post) { Post.find(id, function(err, post) {
test.ok(!!post.published, 'Update boolean field'); test.ok(!!post.published, 'Update boolean field');
test.ok(post.id); test.ok(post.id);
@ -947,7 +949,7 @@ function testOrm(dataSource) {
}); });
it('should handle belongsTo correctly', function(test) { it('should handle belongsTo correctly', function(test) {
var passport = new Passport({ ownerId: 16 }); var passport = new Passport({ownerId: 16});
// sync getter // sync getter
test.equal(passport.owner(), 16); test.equal(passport.owner(), 16);
// sync setter // sync setter
@ -960,14 +962,14 @@ function testOrm(dataSource) {
test.expect(4); test.expect(4);
Post.findOne(function(err, post) { Post.findOne(function(err, post) {
test.ok(post && post.id); test.ok(post && post.id);
Post.findOne({ where: { title: 'hey' }}, function(err, post) { Post.findOne({where: {title: 'hey'}}, function(err, post) {
if (err) { if (err) {
console.log(err); console.log(err);
return test.done(); return test.done();
} }
test.equal(post && post.constructor.modelName, 'Post'); test.equal(post && post.constructor.modelName, 'Post');
test.equal(post && post.title, 'hey'); test.equal(post && post.title, 'hey');
Post.findOne({ where: { title: 'not exists' }}, function(err, post) { Post.findOne({where: {title: 'not exists'}}, function(err, post) {
test.ok(post === null); test.ok(post === null);
test.done(); test.done();
}); });
@ -1050,7 +1052,7 @@ function testOrm(dataSource) {
} }
test.equal(newData.title, post.toObject().title); test.equal(newData.title, post.toObject().title);
test.equal(newData.content, post.toObject().content); test.equal(newData.content, post.toObject().content);
Post.updateOrCreate({ id: 100001, title: 'hey' }, function(err, post) { Post.updateOrCreate({id: 100001, title: 'hey'}, function(err, post) {
if (dataSource.name !== 'mongodb') test.equal(post.id, 100001); if (dataSource.name !== 'mongodb') test.equal(post.id, 100001);
test.equal(post.title, 'hey'); test.equal(post.title, 'hey');
Post.findById(post.id, function(err, post) { Post.findById(post.id, function(err, post) {
@ -1067,18 +1069,18 @@ function testOrm(dataSource) {
User.setter.passwd = function(pass) { User.setter.passwd = function(pass) {
this._passwd = pass + 'salt'; this._passwd = pass + 'salt';
}; };
var u = new User({ passwd: 'qwerty' }); var u = new User({passwd: 'qwerty'});
test.equal(u.passwd, 'qwertysalt'); test.equal(u.passwd, 'qwertysalt');
u.save(function(err, user) { u.save(function(err, user) {
User.findById(user.id, function(err, user) { User.findById(user.id, function(err, user) {
test.ok(user !== u); test.ok(user !== u);
test.equal(user.passwd, 'qwertysalt'); test.equal(user.passwd, 'qwertysalt');
User.all({ where: { passwd: 'qwertysalt' }}, function(err, users) { User.all({where: {passwd: 'qwertysalt'}}, function(err, users) {
test.ok(users[0] !== user); test.ok(users[0] !== user);
test.equal(users[0].passwd, 'qwertysalt'); test.equal(users[0].passwd, 'qwertysalt');
User.create({ passwd: 'asalat' }, function(err, usr) { User.create({passwd: 'asalat'}, function(err, usr) {
test.equal(usr.passwd, 'asalatsalt'); test.equal(usr.passwd, 'asalatsalt');
User.upsert({ passwd: 'heyman' }, function(err, us) { User.upsert({passwd: 'heyman'}, function(err, us) {
test.equal(us.passwd, 'heymansalt'); test.equal(us.passwd, 'heymansalt');
User.findById(us.id, function(err, user) { User.findById(us.id, function(err, user) {
test.equal(user.passwd, 'heymansalt'); test.equal(user.passwd, 'heymansalt');
@ -1093,14 +1095,14 @@ function testOrm(dataSource) {
it('should work with typed and untyped nested collections', function(test) { it('should work with typed and untyped nested collections', function(test) {
var post = new Post; var post = new Post;
var like = post.likes.push({ foo: 'bar' }); var like = post.likes.push({foo: 'bar'});
test.equal(like.constructor.name, 'ListItem'); test.equal(like.constructor.name, 'ListItem');
var related = post.related.push({ hello: 'world' }); var related = post.related.push({hello: 'world'});
test.ok(related.someMethod); test.ok(related.someMethod);
post.save(function(err, p) { post.save(function(err, p) {
test.equal(p.likes.nextid, 2); test.equal(p.likes.nextid, 2);
p.likes.push({ second: 2 }); p.likes.push({second: 2});
p.likes.push({ third: 3 }); p.likes.push({third: 3});
p.save(function(err) { p.save(function(err) {
Post.findById(p.id, function(err, pp) { Post.findById(p.id, function(err, pp) {
test.equal(pp.likes.length, 3); test.equal(pp.likes.length, 3);
@ -1129,11 +1131,11 @@ function testOrm(dataSource) {
it('should find or create', function(test) { it('should find or create', function(test) {
var email = 'some email ' + Math.random(); var email = 'some email ' + Math.random();
User.findOrCreate({ where: { email: email }}, function(err, u, created) { User.findOrCreate({where: {email: email}}, function(err, u, created) {
test.ok(u); test.ok(u);
test.ok(!u.age); test.ok(!u.age);
test.ok(created); test.ok(created);
User.findOrCreate({ where: { email: email }}, { age: 21 }, function(err, u2, created) { User.findOrCreate({where: {email: email}}, {age: 21}, function(err, u2, created) {
test.equals(u.id.toString(), u2.id.toString(), 'Same user ids'); test.equals(u.id.toString(), u2.id.toString(), 'Same user ids');
test.ok(!u2.age); test.ok(!u2.age);
test.ok(!created); test.ok(!created);

View File

@ -4,6 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var async = require('async'); var async = require('async');
var db, User, options, filter; var db, User, options, filter;
@ -13,17 +15,17 @@ describe('crud-with-options', function() {
before(function(done) { before(function(done) {
db = getSchema(); db = getSchema();
User = db.define('User', { User = db.define('User', {
id: { type: Number, id: true }, id: {type: Number, id: true},
seq: { type: Number, index: true }, seq: {type: Number, index: true},
name: { type: String, index: true, sort: true }, name: {type: String, index: true, sort: true},
email: { type: String, index: true }, email: {type: String, index: true},
birthday: { type: Date, index: true }, birthday: {type: Date, index: true},
role: { type: String, index: true }, role: {type: String, index: true},
order: { type: Number, index: true, sort: true }, order: {type: Number, index: true, sort: true},
vip: { type: Boolean }, vip: {type: Boolean},
}); });
options = {}; options = {};
filter = { fields: ['name', 'id'] }; filter = {fields: ['name', 'id']};
db.automigrate(['User'], done); db.automigrate(['User'], done);
@ -96,7 +98,7 @@ describe('crud-with-options', function() {
it('should allow findById(id, filter, cb) for a matching id', it('should allow findById(id, filter, cb) for a matching id',
function(done) { function(done) {
User.create({ name: 'x', email: 'x@y.com' }, function(err, u) { User.create({name: 'x', email: 'x@y.com'}, function(err, u) {
should.not.exist(err); should.not.exist(err);
should.exist(u.id); should.exist(u.id);
User.findById(u.id, filter, function(err, u) { User.findById(u.id, filter, function(err, u) {
@ -112,7 +114,7 @@ describe('crud-with-options', function() {
it('should allow findById(id, options, cb) for a matching id', it('should allow findById(id, options, cb) for a matching id',
function(done) { function(done) {
User.create({ name: 'y', email: 'y@y.com' }, function(err, u) { User.create({name: 'y', email: 'y@y.com'}, function(err, u) {
should.not.exist(err); should.not.exist(err);
should.exist(u.id); should.exist(u.id);
User.findById(u.id, options, function(err, u) { User.findById(u.id, options, function(err, u) {
@ -128,7 +130,7 @@ describe('crud-with-options', function() {
it('should allow findById(id, filter, options, cb) for a matching id', it('should allow findById(id, filter, options, cb) for a matching id',
function(done) { function(done) {
User.create({ name: 'z', email: 'z@y.com' }, function(err, u) { User.create({name: 'z', email: 'z@y.com'}, function(err, u) {
should.not.exist(err); should.not.exist(err);
should.exist(u.id); should.exist(u.id);
User.findById(u.id, filter, options, function(err, u) { User.findById(u.id, filter, options, function(err, u) {
@ -144,7 +146,7 @@ describe('crud-with-options', function() {
it('should allow promise-style findById', it('should allow promise-style findById',
function(done) { function(done) {
User.create({ name: 'w', email: 'w@y.com' }).then(function(u) { User.create({name: 'w', email: 'w@y.com'}).then(function(u) {
should.exist(u.id); should.exist(u.id);
return User.findById(u.id).then(function(u) { return User.findById(u.id).then(function(u) {
should.exist(u); should.exist(u);
@ -194,12 +196,12 @@ describe('crud-with-options', function() {
before(function(done) { before(function(done) {
var people = [ var people = [
{ id: 1, name: 'a', vip: true }, {id: 1, name: 'a', vip: true},
{ id: 2, name: 'b' }, {id: 2, name: 'b'},
{ id: 3, name: 'c' }, {id: 3, name: 'c'},
{ id: 4, name: 'd', vip: true }, {id: 4, name: 'd', vip: true},
{ id: 5, name: 'e' }, {id: 5, name: 'e'},
{ id: 6, name: 'f' }, {id: 6, name: 'f'},
]; ];
// Use automigrate so that serial keys are 1-6 // Use automigrate so that serial keys are 1-6
db.automigrate(['User'], function(err) { db.automigrate(['User'], function(err) {
@ -222,7 +224,7 @@ describe('crud-with-options', function() {
it('should allow findByIds(ids, filter, options, cb)', it('should allow findByIds(ids, filter, options, cb)',
function(done) { function(done) {
User.findByIds([4, 3, 2, 1], User.findByIds([4, 3, 2, 1],
{ where: { vip: true }}, options, function(err, users) { {where: {vip: true}}, options, function(err, users) {
should.exist(users); should.exist(users);
should.not.exist(err); should.not.exist(err);
var names = users.map(function(u) { var names = users.map(function(u) {
@ -249,7 +251,7 @@ describe('crud-with-options', function() {
}); });
it('should allow find(filter, cb)', function(done) { it('should allow find(filter, cb)', function(done) {
User.find({ limit: 3 }, function(err, users) { User.find({limit: 3}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(3); users.should.have.lengthOf(3);
@ -267,15 +269,15 @@ describe('crud-with-options', function() {
}); });
it('should allow find(filter, options)', function() { it('should allow find(filter, options)', function() {
User.find({ limit: 3 }, options); User.find({limit: 3}, options);
}); });
it('should allow find(filter)', function() { it('should allow find(filter)', function() {
User.find({ limit: 3 }); User.find({limit: 3});
}); });
it('should skip trailing undefined args', function(done) { it('should skip trailing undefined args', function(done) {
User.find({ limit: 3 }, function(err, users) { User.find({limit: 3}, function(err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(3); users.should.have.lengthOf(3);
@ -293,7 +295,7 @@ describe('crud-with-options', function() {
it('should throw on an invalid options arg', function() { it('should throw on an invalid options arg', function() {
(function() { (function() {
User.find({ limit: 3 }, 'invalid option', function(err, users) { User.find({limit: 3}, 'invalid option', function(err, users) {
// noop // noop
}); });
}).should.throw('The options argument must be an object'); }).should.throw('The options argument must be an object');
@ -301,7 +303,7 @@ describe('crud-with-options', function() {
it('should throw on an invalid cb arg', function() { it('should throw on an invalid cb arg', function() {
(function() { (function() {
User.find({ limit: 3 }, {}, 'invalid cb'); User.find({limit: 3}, {}, 'invalid cb');
}).should.throw('The cb argument must be a function'); }).should.throw('The cb argument must be a function');
}); });
@ -321,7 +323,7 @@ describe('crud-with-options', function() {
}); });
it('should allow count(where, cb)', function(done) { it('should allow count(where, cb)', function(done) {
User.count({ role: 'lead' }, function(err, n) { User.count({role: 'lead'}, function(err, n) {
should.not.exist(err); should.not.exist(err);
should.exist(n); should.exist(n);
n.should.equal(2); n.should.equal(2);
@ -330,7 +332,7 @@ describe('crud-with-options', function() {
}); });
it('should allow count(where, options, cb)', function(done) { it('should allow count(where, options, cb)', function(done) {
User.count({ role: 'lead' }, options, function(err, n) { User.count({role: 'lead'}, options, function(err, n) {
should.not.exist(err); should.not.exist(err);
should.exist(n); should.exist(n);
n.should.equal(2); n.should.equal(2);
@ -345,7 +347,7 @@ describe('crud-with-options', function() {
before(seed); before(seed);
it('should allow findOne(cb)', function(done) { it('should allow findOne(cb)', function(done) {
User.find({ order: 'id' }, function(err, users) { User.find({order: 'id'}, function(err, users) {
User.findOne(function(e, u) { User.findOne(function(e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
@ -356,7 +358,7 @@ describe('crud-with-options', function() {
}); });
it('should allow findOne(filter, options, cb)', function(done) { it('should allow findOne(filter, options, cb)', function(done) {
User.findOne({ order: 'order' }, options, function(e, u) { User.findOne({order: 'order'}, options, function(e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(1); u.order.should.equal(1);
@ -366,7 +368,7 @@ describe('crud-with-options', function() {
}); });
it('should allow findOne(filter, cb)', function(done) { it('should allow findOne(filter, cb)', function(done) {
User.findOne({ order: 'order' }, function(e, u) { User.findOne({order: 'order'}, function(e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(1); u.order.should.equal(1);
@ -376,7 +378,7 @@ describe('crud-with-options', function() {
}); });
it('should allow trailing undefined args', function(done) { it('should allow trailing undefined args', function(done) {
User.findOne({ order: 'order' }, function(e, u) { User.findOne({order: 'order'}, function(e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(1); u.order.should.equal(1);
@ -417,7 +419,7 @@ describe('crud-with-options', function() {
describe('save', function() { describe('save', function() {
it('should allow save(options, cb)', function(done) { it('should allow save(options, cb)', function(done) {
var options = { foo: 'bar' }; var options = {foo: 'bar'};
var opts; var opts;
User.observe('after save', function(ctx, next) { User.observe('after save', function(ctx, next) {
@ -440,12 +442,12 @@ describe('crud-with-options', function() {
beforeEach(seed); beforeEach(seed);
it('should allow destroyAll(where, options, cb)', function(done) { it('should allow destroyAll(where, options, cb)', function(done) {
User.destroyAll({ name: 'John Lennon' }, options, function(err) { User.destroyAll({name: 'John Lennon'}, options, function(err) {
should.not.exist(err); should.not.exist(err);
User.find({ where: { name: 'John Lennon' }}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({ where: { name: 'Paul McCartney' }}, function(err, data) { User.find({where: {name: 'Paul McCartney'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(1); data.length.should.equal(1);
done(); done();
@ -455,12 +457,12 @@ describe('crud-with-options', function() {
}); });
it('should allow destroyAll(where, cb)', function(done) { it('should allow destroyAll(where, cb)', function(done) {
User.destroyAll({ name: 'John Lennon' }, function(err) { User.destroyAll({name: 'John Lennon'}, function(err) {
should.not.exist(err); should.not.exist(err);
User.find({ where: { name: 'John Lennon' }}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({ where: { name: 'Paul McCartney' }}, function(err, data) { User.find({where: {name: 'Paul McCartney'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(1); data.length.should.equal(1);
done(); done();
@ -472,10 +474,10 @@ describe('crud-with-options', function() {
it('should allow destroyAll(cb)', function(done) { it('should allow destroyAll(cb)', function(done) {
User.destroyAll(function(err) { User.destroyAll(function(err) {
should.not.exist(err); should.not.exist(err);
User.find({ where: { name: 'John Lennon' }}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({ where: { name: 'Paul McCartney' }}, function(err, data) { User.find({where: {name: 'Paul McCartney'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
done(); done();
@ -491,12 +493,12 @@ describe('crud-with-options', function() {
beforeEach(seed); beforeEach(seed);
it('should allow updateAll(where, data, cb)', function(done) { it('should allow updateAll(where, data, cb)', function(done) {
User.update({ name: 'John Lennon' }, { name: 'John Smith' }, function(err) { User.update({name: 'John Lennon'}, {name: 'John Smith'}, function(err) {
should.not.exist(err); should.not.exist(err);
User.find({ where: { name: 'John Lennon' }}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({ where: { name: 'John Smith' }}, function(err, data) { User.find({where: {name: 'John Smith'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(1); data.length.should.equal(1);
done(); done();
@ -506,13 +508,13 @@ describe('crud-with-options', function() {
}); });
it('should allow updateAll(where, data, options, cb)', function(done) { it('should allow updateAll(where, data, options, cb)', function(done) {
User.update({ name: 'John Lennon' }, { name: 'John Smith' }, options, User.update({name: 'John Lennon'}, {name: 'John Smith'}, options,
function(err) { function(err) {
should.not.exist(err); should.not.exist(err);
User.find({ where: { name: 'John Lennon' }}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({ where: { name: 'John Smith' }}, function(err, data) { User.find({where: {name: 'John Smith'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(1); data.length.should.equal(1);
done(); done();
@ -522,11 +524,11 @@ describe('crud-with-options', function() {
}); });
it('should allow updateAll(data, cb)', function(done) { it('should allow updateAll(data, cb)', function(done) {
User.update({ name: 'John Smith' }, function() { User.update({name: 'John Smith'}, function() {
User.find({ where: { name: 'John Lennon' }}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({ where: { name: 'John Smith' }}, function(err, data) { User.find({where: {name: 'John Smith'}}, function(err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(6); data.length.should.equal(6);
done(); done();
@ -564,12 +566,12 @@ describe('upsertWithWhere', function() {
}); });
it('allows upsertWithWhere by accepting where,data and cb as arguments', function(done) { it('allows upsertWithWhere by accepting where,data and cb as arguments', function(done) {
User.upsertWithWhere({ name: 'John Lennon' }, { name: 'John Smith' }, function(err) { User.upsertWithWhere({name: 'John Lennon'}, {name: 'John Smith'}, function(err) {
if (err) return done(err); if (err) return done(err);
User.find({ where: { name: 'John Lennon' }}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function(err, data) {
if (err) return done(err); if (err) return done(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({ where: { name: 'John Smith' }}, function(err, data) { User.find({where: {name: 'John Smith'}}, function(err, data) {
if (err) return done(err); if (err) return done(err);
data.length.should.equal(1); data.length.should.equal(1);
data[0].name.should.equal('John Smith'); data[0].name.should.equal('John Smith');
@ -585,9 +587,9 @@ describe('upsertWithWhere', function() {
it('allows upsertWithWhere by accepting where, data, options, and cb as arguments', function(done) { it('allows upsertWithWhere by accepting where, data, options, and cb as arguments', function(done) {
options = {}; options = {};
User.upsertWithWhere({ name: 'John Lennon' }, { name: 'John Smith' }, options, function(err) { User.upsertWithWhere({name: 'John Lennon'}, {name: 'John Smith'}, options, function(err) {
if (err) return done(err); if (err) return done(err);
User.find({ where: { name: 'John Smith' }}, function(err, data) { User.find({where: {name: 'John Smith'}}, function(err, data) {
if (err) return done(err); if (err) return done(err);
data.length.should.equal(1); data.length.should.equal(1);
data[0].name.should.equal('John Smith'); data[0].name.should.equal('John Smith');
@ -622,10 +624,10 @@ function seed(done) {
order: 1, order: 1,
vip: true, vip: true,
}, },
{ seq: 2, name: 'George Harrison', order: 5, vip: false }, {seq: 2, name: 'George Harrison', order: 5, vip: false},
{ seq: 3, name: 'Ringo Starr', order: 6, vip: false }, {seq: 3, name: 'Ringo Starr', order: 6, vip: false},
{ seq: 4, name: 'Pete Best', order: 4 }, {seq: 4, name: 'Pete Best', order: 4},
{ seq: 5, name: 'Stuart Sutcliffe', order: 3, vip: true }, {seq: 5, name: 'Stuart Sutcliffe', order: 3, vip: true},
]; ];
async.series([ async.series([

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var DataSource = require('../lib/datasource.js').DataSource; var DataSource = require('../lib/datasource.js').DataSource;

View File

@ -4,6 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var db, Model; var db, Model;
@ -12,14 +14,14 @@ describe('datatypes', function() {
before(function(done) { before(function(done) {
db = getSchema(); db = getSchema();
Nested = db.define('Nested', {}); var Nested = db.define('Nested', {});
Model = db.define('Model', { Model = db.define('Model', {
str: String, str: String,
date: Date, date: Date,
num: Number, num: Number,
bool: Boolean, bool: Boolean,
list: { type: [String] }, list: {type: [String]},
arr: Array, arr: Array,
nested: Nested, nested: Nested,
}); });
@ -29,12 +31,12 @@ describe('datatypes', function() {
it('should return 400 when property of type array is set to string value', it('should return 400 when property of type array is set to string value',
function(done) { function(done) {
var myModel = db.define('myModel', { var myModel = db.define('myModel', {
list: { type: ['object'] }, list: {type: ['object']},
}); });
(function() { (function() {
myModel.create({ list: 'This string will crash the server' }); myModel.create({list: 'This string will crash the server'});
}).should.throw({ statusCode: 400 }); }).should.throw({statusCode: 400});
done(); done();
}); });
@ -42,12 +44,12 @@ describe('datatypes', function() {
it('should return 400 when property of type array is set to object value', it('should return 400 when property of type array is set to object value',
function(done) { function(done) {
var myModel = db.define('myModel', { var myModel = db.define('myModel', {
list: { type: ['object'] }, list: {type: ['object']},
}); });
(function() { (function() {
myModel.create({ list: { key: 'This string will crash the server' }}); myModel.create({list: {key: 'This string will crash the server'}});
}).should.throw({ statusCode: 400 }); }).should.throw({statusCode: 400});
done(); done();
}); });
@ -55,12 +57,12 @@ describe('datatypes', function() {
it('throws an error when property of type Date is set to an invalid value', it('throws an error when property of type Date is set to an invalid value',
function() { function() {
var myModel = db.define('myModel', { var myModel = db.define('myModel', {
date: { type: Date }, date: {type: Date},
}); });
(function() { (function() {
myModel.create({ date: 'invalid' }); myModel.create({date: 'invalid'});
}).should.throw({ message: 'Invalid date: invalid' }); }).should.throw({message: 'Invalid date: invalid'});
}); });
it('should keep types when get read data from db', function(done) { it('should keep types when get read data from db', function(done) {
@ -116,7 +118,7 @@ describe('datatypes', function() {
var d = new Date, id; var d = new Date, id;
Model.create({ Model.create({
str: 'hello', date: d, num: '3', bool: 1 }, function(err, m) { str: 'hello', date: d, num: '3', bool: 1}, function(err, m) {
should.not.exist(err); should.not.exist(err);
should.exist(m && m.id); should.exist(m && m.id);
@ -165,7 +167,7 @@ describe('datatypes', function() {
}); });
it('should not coerce nested objects into ModelConstructor types', function() { it('should not coerce nested objects into ModelConstructor types', function() {
var coerced = Model._coerce({ nested: { foo: 'bar' }}); var coerced = Model._coerce({nested: {foo: 'bar'}});
coerced.nested.constructor.name.should.equal('Object'); coerced.nested.constructor.name.should.equal('Object');
}); });
@ -173,10 +175,10 @@ describe('datatypes', function() {
function(done) { function(done) {
db = getSchema(); db = getSchema();
Model = db.define('RequiredNumber', { Model = db.define('RequiredNumber', {
num: { type: Number, required: true }, num: {type: Number, required: true},
}); });
db.automigrate(['Model'], function() { db.automigrate(['Model'], function() {
Model.create({ num: [1, 2, 3] }, function(err, inst) { Model.create({num: [1, 2, 3]}, function(err, inst) {
should.exist(err); should.exist(err);
err.should.have.property('name').equal('ValidationError'); err.should.have.property('name').equal('ValidationError');
done(); done();
@ -190,8 +192,8 @@ describe('datatypes', function() {
TestModel = db.define( TestModel = db.define(
'TestModel', 'TestModel',
{ {
desc: { type: String, required: false }, desc: {type: String, required: false},
stars: { type: Number, required: false }, stars: {type: Number, required: false},
}, },
{ {
persistUndefinedAsNull: true, persistUndefinedAsNull: true,
@ -203,8 +205,8 @@ describe('datatypes', function() {
}); });
it('should set missing optional properties to null', function(done) { it('should set missing optional properties to null', function(done) {
var EXPECTED = { desc: null, stars: null }; var EXPECTED = {desc: null, stars: null};
TestModel.create({ name: 'a-test-name' }, function(err, created) { TestModel.create({name: 'a-test-name'}, function(err, created) {
if (err) return done(err); if (err) return done(err);
created.should.have.properties(EXPECTED); created.should.have.properties(EXPECTED);
@ -217,13 +219,13 @@ describe('datatypes', function() {
}); });
it('should convert property value undefined to null', function(done) { it('should convert property value undefined to null', function(done) {
var EXPECTED = { desc: null, extra: null }; var EXPECTED = {desc: null, extra: null};
if (isStrict) { if (isStrict) {
// SQL-based connectors don't support dynamic properties // SQL-based connectors don't support dynamic properties
delete EXPECTED.extra; delete EXPECTED.extra;
} }
var data = { desc: undefined, extra: undefined }; var data = {desc: undefined, extra: undefined};
TestModel.create(data, function(err, created) { TestModel.create(data, function(err, created) {
if (err) return done(err); if (err) return done(err);
@ -252,7 +254,7 @@ describe('datatypes', function() {
}); });
it('should convert undefined to null on save', function(done) { it('should convert undefined to null on save', function(done) {
var EXPECTED = { desc: null, stars: null, extra: null, dx: null }; var EXPECTED = {desc: null, stars: null, extra: null, dx: null};
if (isStrict) { if (isStrict) {
// SQL-based connectors don't support dynamic properties // SQL-based connectors don't support dynamic properties
delete EXPECTED.extra; delete EXPECTED.extra;
@ -282,14 +284,14 @@ describe('datatypes', function() {
if (TestModel.dataSource.connector.all.length === 4) { if (TestModel.dataSource.connector.all.length === 4) {
TestModel.dataSource.connector.all( TestModel.dataSource.connector.all(
TestModel.modelName, TestModel.modelName,
{ where: { id: created.id }}, {where: {id: created.id}},
{}, {},
cb cb
); );
} else { } else {
TestModel.dataSource.connector.all( TestModel.dataSource.connector.all(
TestModel.modelName, TestModel.modelName,
{ where: { id: created.id }}, {where: {id: created.id}},
cb cb
); );
} }

View File

@ -4,6 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var async = require('async'); var async = require('async');
@ -18,31 +20,31 @@ var db, Category, Product, Tool, Widget, Thing, Person;
var setupProducts = function(ids, done) { var setupProducts = function(ids, done) {
async.series([ async.series([
function(next) { function(next) {
Tool.create({ name: 'Tool Z' }, function(err, inst) { Tool.create({name: 'Tool Z'}, function(err, inst) {
ids.toolZ = inst.id; ids.toolZ = inst.id;
next(); next();
}); });
}, },
function(next) { function(next) {
Widget.create({ name: 'Widget Z' }, function(err, inst) { Widget.create({name: 'Widget Z'}, function(err, inst) {
ids.widgetZ = inst.id; ids.widgetZ = inst.id;
next(); next();
}); });
}, },
function(next) { function(next) {
Tool.create({ name: 'Tool A', active: false }, function(err, inst) { Tool.create({name: 'Tool A', active: false}, function(err, inst) {
ids.toolA = inst.id; ids.toolA = inst.id;
next(); next();
}); });
}, },
function(next) { function(next) {
Widget.create({ name: 'Widget A' }, function(err, inst) { Widget.create({name: 'Widget A'}, function(err, inst) {
ids.widgetA = inst.id; ids.widgetA = inst.id;
next(); next();
}); });
}, },
function(next) { function(next) {
Widget.create({ name: 'Widget B', active: false }, function(err, inst) { Widget.create({name: 'Widget B', active: false}, function(err, inst) {
ids.widgetB = inst.id; ids.widgetB = inst.id;
next(); next();
}); });
@ -63,10 +65,10 @@ describe('default scope', function() {
name: String, name: String,
kind: String, kind: String,
description: String, description: String,
active: { type: Boolean, default: true }, active: {type: Boolean, default: true},
}, { }, {
scope: { order: 'name' }, scope: {order: 'name'},
scopes: { active: { where: { active: true }}}, scopes: {active: {where: {active: true}}},
}); });
Product.lookupModel = function(data) { Product.lookupModel = function(data) {
@ -77,23 +79,23 @@ describe('default scope', function() {
Tool = db.define('Tool', Product.definition.properties, { Tool = db.define('Tool', Product.definition.properties, {
base: 'Product', base: 'Product',
scope: { where: { kind: 'Tool' }, order: 'name' }, scope: {where: {kind: 'Tool'}, order: 'name'},
scopes: { active: { where: { active: true }}}, scopes: {active: {where: {active: true}}},
mongodb: { collection: 'Product' }, mongodb: {collection: 'Product'},
memory: { collection: 'Product' }, memory: {collection: 'Product'},
}); });
Widget = db.define('Widget', Product.definition.properties, { Widget = db.define('Widget', Product.definition.properties, {
base: 'Product', base: 'Product',
properties: { kind: 'Widget' }, properties: {kind: 'Widget'},
scope: { where: { kind: 'Widget' }, order: 'name' }, scope: {where: {kind: 'Widget'}, order: 'name'},
scopes: { active: { where: { active: true }}}, scopes: {active: {where: {active: true}}},
mongodb: { collection: 'Product' }, mongodb: {collection: 'Product'},
memory: { collection: 'Product' }, memory: {collection: 'Product'},
}); });
Person = db.define('Person', { name: String }, { Person = db.define('Person', {name: String}, {
scope: { include: 'things' }, scope: {include: 'things'},
forceId: false, forceId: false,
}); });
@ -101,23 +103,23 @@ describe('default scope', function() {
// like save, updateAttributes // like save, updateAttributes
var scopeFn = function(target, inst) { var scopeFn = function(target, inst) {
return { where: { kind: this.modelName }}; return {where: {kind: this.modelName}};
}; };
var propertiesFn = function(target, inst) { var propertiesFn = function(target, inst) {
return { kind: this.modelName }; return {kind: this.modelName};
}; };
Thing = db.define('Thing', Product.definition.properties, { Thing = db.define('Thing', Product.definition.properties, {
base: 'Product', base: 'Product',
attributes: propertiesFn, attributes: propertiesFn,
scope: scopeFn, scope: scopeFn,
mongodb: { collection: 'Product' }, mongodb: {collection: 'Product'},
memory: { collection: 'Product' }, memory: {collection: 'Product'},
}); });
Category.hasMany(Product); Category.hasMany(Product);
Category.hasMany(Tool, { scope: { order: 'name DESC' }}); Category.hasMany(Tool, {scope: {order: 'name DESC'}});
Category.hasMany(Widget); Category.hasMany(Widget);
Category.hasMany(Thing); Category.hasMany(Thing);
@ -141,10 +143,10 @@ describe('default scope', function() {
}); });
it('should return a scoped instance', function() { it('should return a scoped instance', function() {
var p = new Tool({ name: 'Product A', kind: 'ignored' }); var p = new Tool({name: 'Product A', kind: 'ignored'});
p.name.should.equal('Product A'); p.name.should.equal('Product A');
p.kind.should.equal('Tool'); p.kind.should.equal('Tool');
p.setAttributes({ kind: 'ignored' }); p.setAttributes({kind: 'ignored'});
p.kind.should.equal('Tool'); p.kind.should.equal('Tool');
p.setAttribute('kind', 'other'); // currently not enforced p.setAttribute('kind', 'other'); // currently not enforced
@ -152,7 +154,7 @@ describe('default scope', function() {
}); });
it('should create a scoped instance - tool', function(done) { it('should create a scoped instance - tool', function(done) {
Tool.create({ name: 'Product A', kind: 'ignored' }, function(err, p) { Tool.create({name: 'Product A', kind: 'ignored'}, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.name.should.equal('Product A'); p.name.should.equal('Product A');
p.kind.should.equal('Tool'); p.kind.should.equal('Tool');
@ -162,7 +164,7 @@ describe('default scope', function() {
}); });
it('should create a scoped instance - widget', function(done) { it('should create a scoped instance - widget', function(done) {
Widget.create({ name: 'Product B', kind: 'ignored' }, function(err, p) { Widget.create({name: 'Product B', kind: 'ignored'}, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.name.should.equal('Product B'); p.name.should.equal('Product B');
p.kind.should.equal('Widget'); p.kind.should.equal('Widget');
@ -173,7 +175,7 @@ describe('default scope', function() {
it('should update a scoped instance - updateAttributes', function(done) { it('should update a scoped instance - updateAttributes', function(done) {
Tool.findById(ids.productA, function(err, p) { Tool.findById(ids.productA, function(err, p) {
p.updateAttributes({ description: 'A thing...', kind: 'ingored' }, function(err, inst) { p.updateAttributes({description: 'A thing...', kind: 'ingored'}, function(err, inst) {
should.not.exist(err); should.not.exist(err);
p.name.should.equal('Product A'); p.name.should.equal('Product A');
p.kind.should.equal('Tool'); p.kind.should.equal('Tool');
@ -201,7 +203,7 @@ describe('default scope', function() {
}); });
it('should update a scoped instance - updateOrCreate', function(done) { it('should update a scoped instance - updateOrCreate', function(done) {
var data = { id: ids.productA, description: 'Anything...', kind: 'ingored' }; var data = {id: ids.productA, description: 'Anything...', kind: 'ingored'};
Tool.updateOrCreate(data, function(err, p) { Tool.updateOrCreate(data, function(err, p) {
should.not.exist(err); should.not.exist(err);
p.name.should.equal('Product A'); p.name.should.equal('Product A');
@ -277,7 +279,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - order override', function(done) { it('should apply default scope - order override', function(done) {
Product.find({ order: 'name DESC' }, function(err, products) { Product.find({order: 'name DESC'}, function(err, products) {
should.not.exist(err); should.not.exist(err);
products.should.have.length(5); products.should.have.length(5);
products[0].name.should.equal('Widget Z'); products[0].name.should.equal('Widget Z');
@ -300,7 +302,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - where (widget)', function(done) { it('should apply default scope - where (widget)', function(done) {
Widget.find({ where: { active: true }}, function(err, products) { Widget.find({where: {active: true}}, function(err, products) {
should.not.exist(err); should.not.exist(err);
products.should.have.length(2); products.should.have.length(2);
products[0].name.should.equal('Widget A'); products[0].name.should.equal('Widget A');
@ -310,7 +312,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - order (widget)', function(done) { it('should apply default scope - order (widget)', function(done) {
Widget.find({ order: 'name DESC' }, function(err, products) { Widget.find({order: 'name DESC'}, function(err, products) {
should.not.exist(err); should.not.exist(err);
products.should.have.length(3); products.should.have.length(3);
products[0].name.should.equal('Widget Z'); products[0].name.should.equal('Widget Z');
@ -405,7 +407,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - where', function(done) { it('should apply default scope - where', function(done) {
Widget.count({ name: 'Widget Z' }, function(err, count) { Widget.count({name: 'Widget Z'}, function(err, count) {
should.not.exist(err); should.not.exist(err);
count.should.equal(1); count.should.equal(1);
done(); done();
@ -413,7 +415,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - no match', function(done) { it('should apply default scope - no match', function(done) {
Tool.count({ name: 'Widget Z' }, function(err, count) { Tool.count({name: 'Widget Z'}, function(err, count) {
should.not.exist(err); should.not.exist(err);
count.should.equal(0); count.should.equal(0);
done(); done();
@ -491,9 +493,9 @@ describe('default scope', function() {
}); });
it('should apply default scope', function(done) { it('should apply default scope', function(done) {
Widget.update({ active: false }, { active: true, kind: 'ignored' }, function(err) { Widget.update({active: false}, {active: true, kind: 'ignored'}, function(err) {
should.not.exist(err); should.not.exist(err);
Widget.find({ where: { active: true }}, function(err, products) { Widget.find({where: {active: true}}, function(err, products) {
should.not.exist(err); should.not.exist(err);
products.should.have.length(3); products.should.have.length(3);
products[0].name.should.equal('Widget A'); products[0].name.should.equal('Widget A');
@ -505,7 +507,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - no match', function(done) { it('should apply default scope - no match', function(done) {
Tool.update({ name: 'Widget A' }, { name: 'Ignored' }, function(err) { Tool.update({name: 'Widget A'}, {name: 'Ignored'}, function(err) {
should.not.exist(err); should.not.exist(err);
Product.findById(ids.widgetA, function(err, product) { Product.findById(ids.widgetA, function(err, product) {
should.not.exist(err); should.not.exist(err);
@ -516,7 +518,7 @@ describe('default scope', function() {
}); });
it('should have updated within scope', function(done) { it('should have updated within scope', function(done) {
Product.find({ where: { active: true }}, function(err, products) { Product.find({where: {active: true}}, function(err, products) {
should.not.exist(err); should.not.exist(err);
products.should.have.length(4); products.should.have.length(4);
products[0].name.should.equal('Tool Z'); products[0].name.should.equal('Tool Z');
@ -538,7 +540,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - custom where', function(done) { it('should apply default scope - custom where', function(done) {
Widget.remove({ name: 'Widget A' }, function(err) { Widget.remove({name: 'Widget A'}, function(err) {
should.not.exist(err); should.not.exist(err);
Product.find(function(err, products) { Product.find(function(err, products) {
products.should.have.length(4); products.should.have.length(4);
@ -552,7 +554,7 @@ describe('default scope', function() {
}); });
it('should apply default scope - custom where (no match)', function(done) { it('should apply default scope - custom where (no match)', function(done) {
Tool.remove({ name: 'Widget Z' }, function(err) { Tool.remove({name: 'Widget Z'}, function(err) {
should.not.exist(err); should.not.exist(err);
Product.find(function(err, products) { Product.find(function(err, products) {
products.should.have.length(4); products.should.have.length(4);
@ -578,7 +580,7 @@ describe('default scope', function() {
}); });
it('should create a scoped instance - tool', function(done) { it('should create a scoped instance - tool', function(done) {
Tool.create({ name: 'Tool B' }, function(err, p) { Tool.create({name: 'Tool B'}, function(err, p) {
should.not.exist(err); should.not.exist(err);
Product.find(function(err, products) { Product.find(function(err, products) {
products.should.have.length(3); products.should.have.length(3);
@ -650,7 +652,7 @@ describe('default scope', function() {
}); });
it('should create a scoped instance - widget', function(done) { it('should create a scoped instance - widget', function(done) {
Widget.create({ name: 'Product', kind: 'ignored' }, function(err, p) { Widget.create({name: 'Product', kind: 'ignored'}, function(err, p) {
p.name.should.equal('Product'); p.name.should.equal('Product');
p.kind.should.equal('Widget'); p.kind.should.equal('Widget');
done(); done();
@ -658,7 +660,7 @@ describe('default scope', function() {
}); });
it('should create a scoped instance - thing', function(done) { it('should create a scoped instance - thing', function(done) {
Thing.create({ name: 'Product', kind: 'ignored' }, function(err, p) { Thing.create({name: 'Product', kind: 'ignored'}, function(err, p) {
p.name.should.equal('Product'); p.name.should.equal('Product');
p.kind.should.equal('Thing'); p.kind.should.equal('Thing');
done(); done();
@ -666,7 +668,7 @@ describe('default scope', function() {
}); });
it('should find a scoped instance - widget', function(done) { it('should find a scoped instance - widget', function(done) {
Widget.findOne({ where: { name: 'Product' }}, function(err, p) { Widget.findOne({where: {name: 'Product'}}, function(err, p) {
p.name.should.equal('Product'); p.name.should.equal('Product');
p.kind.should.equal('Widget'); p.kind.should.equal('Widget');
done(); done();
@ -674,7 +676,7 @@ describe('default scope', function() {
}); });
it('should find a scoped instance - thing', function(done) { it('should find a scoped instance - thing', function(done) {
Thing.findOne({ where: { name: 'Product' }}, function(err, p) { Thing.findOne({where: {name: 'Product'}}, function(err, p) {
p.name.should.equal('Product'); p.name.should.equal('Product');
p.kind.should.equal('Thing'); p.kind.should.equal('Thing');
done(); done();
@ -682,7 +684,7 @@ describe('default scope', function() {
}); });
it('should find a scoped instance - thing', function(done) { it('should find a scoped instance - thing', function(done) {
Product.find({ where: { name: 'Product' }}, function(err, products) { Product.find({where: {name: 'Product'}}, function(err, products) {
products.should.have.length(2); products.should.have.length(2);
products[0].name.should.equal('Product'); products[0].name.should.equal('Product');
products[1].name.should.equal('Product'); products[1].name.should.equal('Product');
@ -704,20 +706,20 @@ describe('default scope', function() {
}); });
before(function(done) { before(function(done) {
Category.create({ name: 'Category A' }, function(err, cat) { Category.create({name: 'Category A'}, function(err, cat) {
ids.categoryA = cat.id; ids.categoryA = cat.id;
async.series([ async.series([
function(next) { function(next) {
cat.widgets.create({ name: 'Widget B', kind: 'ignored' }, next); cat.widgets.create({name: 'Widget B', kind: 'ignored'}, next);
}, },
function(next) { function(next) {
cat.widgets.create({ name: 'Widget A' }, next); cat.widgets.create({name: 'Widget A'}, next);
}, },
function(next) { function(next) {
cat.tools.create({ name: 'Tool A' }, next); cat.tools.create({name: 'Tool A'}, next);
}, },
function(next) { function(next) {
cat.things.create({ name: 'Thing A' }, next); cat.things.create({name: 'Thing A'}, next);
}, },
], done); ], done);
}); });
@ -799,7 +801,7 @@ describe('default scope', function() {
it('should create related item with default scope', function(done) { it('should create related item with default scope', function(done) {
Category.findById(ids.categoryA, function(err, cat) { Category.findById(ids.categoryA, function(err, cat) {
cat.tools.create({ name: 'Tool B' }, done); cat.tools.create({name: 'Tool B'}, done);
}); });
}); });
@ -825,8 +827,8 @@ describe('default scope', function() {
}); });
before(function(done) { before(function(done) {
Person.create({ id: 1, name: 'Person A' }, function(err, person) { Person.create({id: 1, name: 'Person A'}, function(err, person) {
person.things.create({ name: 'Thing A' }, done); person.things.create({name: 'Thing A'}, done);
}); });
}); });

View File

@ -4,6 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var db = getSchema(); var db = getSchema();
@ -14,8 +16,8 @@ describe('defaults', function() {
before(function() { before(function() {
Server = db.define('Server', { Server = db.define('Server', {
host: String, host: String,
port: { type: Number, default: 80 }, port: {type: Number, default: 80},
createdAt: { type: Date, default: '$now' }, createdAt: {type: Date, default: '$now'},
}); });
}); });
@ -43,10 +45,10 @@ describe('defaults', function() {
}); });
it('should ignore defaults with limited fields', function(done) { it('should ignore defaults with limited fields', function(done) {
Server.create({ host: 'localhost', port: 8080 }, function(err, s) { Server.create({host: 'localhost', port: 8080}, function(err, s) {
should.not.exist(err); should.not.exist(err);
s.port.should.equal(8080); s.port.should.equal(8080);
Server.find({ fields: ['host'] }, function(err, servers) { Server.find({fields: ['host']}, function(err, servers) {
servers[0].host.should.equal('localhost'); servers[0].host.should.equal('localhost');
servers[0].should.have.property('host'); servers[0].should.have.property('host');
servers[0].should.have.property('port', undefined); servers[0].should.have.property('port', undefined);
@ -56,7 +58,7 @@ describe('defaults', function() {
}); });
it('should apply defaults in upsert create', function(done) { it('should apply defaults in upsert create', function(done) {
Server.upsert({ port: 8181 }, function(err, server) { Server.upsert({port: 8181}, function(err, server) {
should.not.exist(err); should.not.exist(err);
should.exist(server.createdAt); should.exist(server.createdAt);
done(); done();
@ -65,7 +67,7 @@ describe('defaults', function() {
it('should preserve defaults in upsert update', function(done) { it('should preserve defaults in upsert update', function(done) {
Server.findOne({}, function(err, server) { Server.findOne({}, function(err, server) {
Server.upsert({ id: server.id, port: 1337 }, function(err, s) { Server.upsert({id: server.id, port: 1337}, function(err, s) {
should.not.exist(err); should.not.exist(err);
(Number(1337)).should.equal(s.port); (Number(1337)).should.equal(s.port);
server.createdAt.should.eql(s.createdAt); server.createdAt.should.eql(s.createdAt);

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var jdb = require('../'); var jdb = require('../');
var DataSource = jdb.DataSource; var DataSource = jdb.DataSource;
var should = require('./init.js'); var should = require('./init.js');
@ -11,11 +13,11 @@ describe('Memory connector with mocked discovery', function() {
var ds; var ds;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
var models = [{ type: 'table', name: 'CUSTOMER', owner: 'STRONGLOOP' }, var models = [{type: 'table', name: 'CUSTOMER', owner: 'STRONGLOOP'},
{ type: 'table', name: 'INVENTORY', owner: 'STRONGLOOP' }, {type: 'table', name: 'INVENTORY', owner: 'STRONGLOOP'},
{ type: 'table', name: 'LOCATION', owner: 'STRONGLOOP' }]; {type: 'table', name: 'LOCATION', owner: 'STRONGLOOP'}];
ds.discoverModelDefinitions = function(options, cb) { ds.discoverModelDefinitions = function(options, cb) {
process.nextTick(function() { process.nextTick(function() {
@ -102,7 +104,7 @@ describe('Memory connector with mocked discovery', function() {
it('should not convert table/column names with null custom mapper', it('should not convert table/column names with null custom mapper',
function(done) { function(done) {
ds.discoverSchemas('INVENTORY', { nameMapper: null }, function(err, schemas) { ds.discoverSchemas('INVENTORY', {nameMapper: null}, function(err, schemas) {
if (err) return done(err); if (err) return done(err);
schemas.should.have.property('STRONGLOOP.INVENTORY'); schemas.should.have.property('STRONGLOOP.INVENTORY');
var s = schemas['STRONGLOOP.INVENTORY']; var s = schemas['STRONGLOOP.INVENTORY'];
@ -117,8 +119,8 @@ describe('Memory connector with mocked discovery', function() {
function(done) { function(done) {
var models = { var models = {
inventory: { inventory: {
product: { type: 'string' }, product: {type: 'string'},
location: { type: 'string' }, location: {type: 'string'},
}, },
}; };
ds.connector.discoverSchemas = function(modelName, options, cb) { ds.connector.discoverSchemas = function(modelName, options, cb) {
@ -126,7 +128,7 @@ describe('Memory connector with mocked discovery', function() {
cb(null, models); cb(null, models);
}); });
}; };
ds.discoverSchemas('INVENTORY', { nameMapper: null }, function(err, schemas) { ds.discoverSchemas('INVENTORY', {nameMapper: null}, function(err, schemas) {
if (err) return done(err); if (err) return done(err);
schemas.should.be.eql(models); schemas.should.be.eql(models);
done(); done();
@ -137,8 +139,8 @@ describe('Memory connector with mocked discovery', function() {
function(done) { function(done) {
var models = { var models = {
inventory: { inventory: {
product: { type: 'string' }, product: {type: 'string'},
location: { type: 'string' }, location: {type: 'string'},
}, },
}; };
ds.connector.discoverSchemas = function(modelName, options, cb) { ds.connector.discoverSchemas = function(modelName, options, cb) {
@ -184,7 +186,7 @@ describe('Memory connector with mocked discovery', function() {
name: 'Inventory', name: 'Inventory',
options: { options: {
idInjection: false, idInjection: false,
memory: { schema: 'STRONGLOOP', table: 'INVENTORY' }, memory: {schema: 'STRONGLOOP', table: 'INVENTORY'},
}, },
properties: { properties: {
available: { available: {
@ -285,11 +287,11 @@ describe('Memory connector with mocked discovery', function() {
describe('discoverModelDefinitions', function() { describe('discoverModelDefinitions', function() {
var ds; var ds;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
var models = [{ type: 'table', name: 'CUSTOMER', owner: 'STRONGLOOP' }, var models = [{type: 'table', name: 'CUSTOMER', owner: 'STRONGLOOP'},
{ type: 'table', name: 'INVENTORY', owner: 'STRONGLOOP' }, {type: 'table', name: 'INVENTORY', owner: 'STRONGLOOP'},
{ type: 'table', name: 'LOCATION', owner: 'STRONGLOOP' }]; {type: 'table', name: 'LOCATION', owner: 'STRONGLOOP'}];
ds.connector.discoverModelDefinitions = function(options, cb) { ds.connector.discoverModelDefinitions = function(options, cb) {
process.nextTick(function() { process.nextTick(function() {
@ -352,7 +354,7 @@ describe('discoverModelProperties', function() {
var ds; var ds;
var modelProperties; var modelProperties;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
modelProperties = [{ modelProperties = [{
owner: 'STRONGLOOP', owner: 'STRONGLOOP',
@ -436,9 +438,9 @@ describe('discoverModelProperties', function() {
describe('discoverPrimaryKeys', function() { describe('discoverPrimaryKeys', function() {
var ds; var ds;
var modelProperties; var modelProperties, primaryKeys;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
primaryKeys = [ primaryKeys = [
{ {
@ -496,9 +498,9 @@ describe('discoverPrimaryKeys', function() {
describe('discoverForeignKeys', function() { describe('discoverForeignKeys', function() {
var ds; var ds;
var modelProperties; var modelProperties, foreignKeys;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
foreignKeys = [{ foreignKeys = [{
fkOwner: 'STRONGLOOP', fkOwner: 'STRONGLOOP',
@ -553,9 +555,9 @@ describe('discoverForeignKeys', function() {
describe('discoverExportedForeignKeys', function() { describe('discoverExportedForeignKeys', function() {
var ds; var ds;
var modelProperties; var modelProperties, exportedForeignKeys;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
exportedForeignKeys = [{ exportedForeignKeys = [{
fkName: 'PRODUCT_FK', fkName: 'PRODUCT_FK',
@ -610,9 +612,9 @@ describe('discoverExportedForeignKeys', function() {
}); });
describe('Mock connector', function() { describe('Mock connector', function() {
mockConnectors = require('./mock-connectors'); var mockConnectors = require('./mock-connectors');
describe('customFieldSettings', function() { describe('customFieldSettings', function() {
ds = new DataSource(mockConnectors.customFieldSettings); var ds = new DataSource(mockConnectors.customFieldSettings);
it('should be present in discoverSchemas', function(done) { it('should be present in discoverSchemas', function(done) {
ds.discoverSchemas('person', function(err, schemas) { ds.discoverSchemas('person', function(err, schemas) {
@ -630,7 +632,7 @@ describe('Default memory connector', function() {
var ds, nonExistantError = 'Table \'NONEXISTENT\' does not exist.'; var ds, nonExistantError = 'Table \'NONEXISTENT\' does not exist.';
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
}); });
it('discoverSchema should return an error when table does not exist', function(done) { it('discoverSchema should return an error when table does not exist', function(done) {

View File

@ -6,6 +6,8 @@
/*global describe,it*/ /*global describe,it*/
/*jshint expr:true */ /*jshint expr:true */
'use strict';
require('should'); require('should');
var GeoPoint = require('../lib/geo').GeoPoint; var GeoPoint = require('../lib/geo').GeoPoint;
@ -23,7 +25,7 @@ describe('GeoPoint', function() {
}); });
it('should support a valid object', function() { it('should support a valid object', function() {
var point = new GeoPoint({ lat: -34, lng: 150 }); var point = new GeoPoint({lat: -34, lng: 150});
point.lat.should.equal(-34); point.lat.should.equal(-34);
point.lng.should.equal(150); point.lng.should.equal(150);
@ -85,7 +87,7 @@ describe('GeoPoint', function() {
it('should return a string in the form "lat,lng"', function() { it('should return a string in the form "lat,lng"', function() {
var point = new GeoPoint({ lat: -34, lng: 150 }); var point = new GeoPoint({lat: -34, lng: 150});
point.toString().should.equal('-34,150'); point.toString().should.equal('-34,150');
}); });
@ -93,8 +95,8 @@ describe('GeoPoint', function() {
describe('distance calculation between two points', function() { describe('distance calculation between two points', function() {
var here = new GeoPoint({ lat: 40.77492964101182, lng: -73.90950187151662 }); var here = new GeoPoint({lat: 40.77492964101182, lng: -73.90950187151662});
var there = new GeoPoint({ lat: 40.7753227, lng: -73.909217 }); var there = new GeoPoint({lat: 40.7753227, lng: -73.909217});
it('should return value in miles by default', function() { it('should return value in miles by default', function() {
@ -114,27 +116,27 @@ describe('GeoPoint', function() {
* - `degrees` * - `degrees`
*/ */
var distance = here.distanceTo(there, { type: 'radians' }); var distance = here.distanceTo(there, {type: 'radians'});
distance.should.be.a.Number; distance.should.be.a.Number;
distance.should.be.approximately(0.000007825491914348416, DELTA); distance.should.be.approximately(0.000007825491914348416, DELTA);
distance = here.distanceTo(there, { type: 'kilometers' }); distance = here.distanceTo(there, {type: 'kilometers'});
distance.should.be.a.Number; distance.should.be.a.Number;
distance.should.be.approximately(0.04985613511367009, DELTA); distance.should.be.approximately(0.04985613511367009, DELTA);
distance = here.distanceTo(there, { type: 'meters' }); distance = here.distanceTo(there, {type: 'meters'});
distance.should.be.a.Number; distance.should.be.a.Number;
distance.should.be.approximately(49.856135113670085, DELTA); distance.should.be.approximately(49.856135113670085, DELTA);
distance = here.distanceTo(there, { type: 'miles' }); distance = here.distanceTo(there, {type: 'miles'});
distance.should.be.a.Number; distance.should.be.a.Number;
distance.should.be.approximately(0.03097916611592679, DELTA); distance.should.be.approximately(0.03097916611592679, DELTA);
distance = here.distanceTo(there, { type: 'feet' }); distance = here.distanceTo(there, {type: 'feet'});
distance.should.be.a.Number; distance.should.be.a.Number;
distance.should.be.approximately(163.56999709209347, DELTA); distance.should.be.approximately(163.56999709209347, DELTA);
distance = here.distanceTo(there, { type: 'degrees' }); distance = here.distanceTo(there, {type: 'degrees'});
distance.should.be.a.Number; distance.should.be.a.Number;
distance.should.be.approximately(0.0004483676593058972, DELTA); distance.should.be.approximately(0.0004483676593058972, DELTA);
}); });

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var traverse = require('traverse'); var traverse = require('traverse');

View File

@ -2,6 +2,7 @@
// Node module: loopback-datasource-juggler // Node module: loopback-datasource-juggler
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
module.exports = HookMonitor; module.exports = HookMonitor;

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var lastId = 0; var lastId = 0;
exports.next = function() { exports.next = function() {

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
// This test written in mocha+should.js // This test written in mocha+should.js
var should = require('./init.js'); var should = require('./init.js');
@ -19,7 +21,7 @@ describe('hooks', function() {
db = getSchema(); db = getSchema();
User = db.define('User', { User = db.define('User', {
email: { type: String, index: true }, email: {type: String, index: true},
name: String, name: String,
password: String, password: String,
state: String, state: String,
@ -48,7 +50,7 @@ describe('hooks', function() {
this.name += ' Rozental'; this.name += ' Rozental';
} }
}; };
User.create({ name: 'Nickolay' }, function(err, u) { User.create({name: 'Nickolay'}, function(err, u) {
u.id.should.be.ok; u.id.should.be.ok;
u.name.should.equal('Nickolay Rozental'); u.name.should.equal('Nickolay Rozental');
done(); done();
@ -131,7 +133,7 @@ describe('hooks', function() {
it('should be triggered on updateAttributes', function(done) { it('should be triggered on updateAttributes', function(done) {
User.create(function(err, user) { User.create(function(err, user) {
addHooks('Save', done); addHooks('Save', done);
user.updateAttributes({ name: 'Anatoliy' }); user.updateAttributes({name: 'Anatoliy'});
}); });
}); });
@ -165,7 +167,7 @@ describe('hooks', function() {
password: '53cr3t', password: '53cr3t',
}, function() { }, function() {
User.findOne({ User.findOne({
where: { email: 'james.bond@example.com' }, where: {email: 'james.bond@example.com'},
}, function(err, jb) { }, function(err, jb) {
jb.password.should.equal('hash'); jb.password.should.equal('hash');
done(); done();
@ -188,7 +190,7 @@ describe('hooks', function() {
should.exist(u); should.exist(u);
u.password.should.equal('hash'); u.password.should.equal('hash');
User.findOne({ User.findOne({
where: { email: 'james.bond@example.com' }, where: {email: 'james.bond@example.com'},
}, function(err, jb) { }, function(err, jb) {
jb.password.should.equal('hash'); jb.password.should.equal('hash');
done(); done();
@ -234,7 +236,7 @@ describe('hooks', function() {
it('should be triggered on updateAttributes', function(done) { it('should be triggered on updateAttributes', function(done) {
User.create(function(err, user) { User.create(function(err, user) {
addHooks('Update', done); addHooks('Update', done);
user.updateAttributes({ name: 'Anatoliy' }); user.updateAttributes({name: 'Anatoliy'});
}); });
}); });
@ -252,7 +254,7 @@ describe('hooks', function() {
data.should.have.keys('name', 'email'); data.should.have.keys('name', 'email');
done(); done();
}; };
user.updateAttributes({ name: 1, email: 2 }); user.updateAttributes({name: 1, email: 2});
}); });
}); });
@ -399,7 +401,7 @@ describe('hooks', function() {
}); });
it('should describe updateAttributes sequence', function(done) { it('should describe updateAttributes sequence', function(done) {
user.updateAttributes({ name: 'Antony' }, function() { user.updateAttributes({name: 'Antony'}, function() {
life.should.eql([ life.should.eql([
'beforeValidate', 'beforeValidate',
'afterValidate', 'afterValidate',

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var async = require('async'); var async = require('async');
var assert = require('assert'); var assert = require('assert');
@ -16,7 +18,7 @@ describe('include', function() {
before(setup); before(setup);
it('should fetch belongsTo relation', function(done) { it('should fetch belongsTo relation', function(done) {
Passport.find({ include: 'owner' }, function(err, passports) { Passport.find({include: 'owner'}, function(err, passports) {
passports.length.should.be.ok; passports.length.should.be.ok;
passports.forEach(function(p) { passports.forEach(function(p) {
p.__cachedRelations.should.have.property('owner'); p.__cachedRelations.should.have.property('owner');
@ -39,7 +41,7 @@ describe('include', function() {
}); });
it('should fetch hasMany relation', function(done) { it('should fetch hasMany relation', function(done) {
User.find({ include: 'posts' }, function(err, users) { User.find({include: 'posts'}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
@ -59,7 +61,7 @@ describe('include', function() {
}); });
it('should fetch Passport - Owner - Posts', function(done) { it('should fetch Passport - Owner - Posts', function(done) {
Passport.find({ include: { owner: 'posts' }}, function(err, passports) { Passport.find({include: {owner: 'posts'}}, function(err, passports) {
should.not.exist(err); should.not.exist(err);
should.exist(passports); should.exist(passports);
@ -91,7 +93,7 @@ describe('include', function() {
}); });
it('should fetch Passport - Owner - empty Posts', function(done) { it('should fetch Passport - Owner - empty Posts', function(done) {
Passport.findOne({ where: { number: '4' }, include: { owner: 'posts' }}, function(err, passport) { Passport.findOne({where: {number: '4'}, include: {owner: 'posts'}}, function(err, passport) {
should.not.exist(err); should.not.exist(err);
should.exist(passport); should.exist(passport);
passport.__cachedRelations.should.have.property('owner'); passport.__cachedRelations.should.have.property('owner');
@ -113,7 +115,7 @@ describe('include', function() {
}); });
it('should fetch Passport - Owner - Posts - alternate syntax', function(done) { it('should fetch Passport - Owner - Posts - alternate syntax', function(done) {
Passport.find({ include: { owner: { relation: 'posts' }}}, function(err, passports) { Passport.find({include: {owner: {relation: 'posts'}}}, function(err, passports) {
should.not.exist(err); should.not.exist(err);
should.exist(passports); should.exist(passports);
passports.length.should.be.ok; passports.length.should.be.ok;
@ -125,7 +127,7 @@ describe('include', function() {
it('should fetch Passports - User - Posts - User', function(done) { it('should fetch Passports - User - Posts - User', function(done) {
Passport.find({ Passport.find({
include: { owner: { posts: 'author' }}, include: {owner: {posts: 'author'}},
}, function(err, passports) { }, function(err, passports) {
should.not.exist(err); should.not.exist(err);
should.exist(passports); should.exist(passports);
@ -155,7 +157,7 @@ describe('include', function() {
it('should fetch Passports with include scope on Posts', function(done) { it('should fetch Passports with include scope on Posts', function(done) {
Passport.find({ Passport.find({
include: { owner: { relation: 'posts', scope: { include: {owner: {relation: 'posts', scope: {
fields: ['title'], include: ['author'], fields: ['title'], include: ['author'],
order: 'title DESC', order: 'title DESC',
}}}, }}},
@ -282,9 +284,9 @@ describe('include', function() {
scope: { scope: {
where: { where: {
and: [ and: [
{ id: 1 }, {id: 1},
{ userId: 1 }, {userId: 1},
{ title: 'Post A' }, {title: 'Post A'},
], ],
}, },
}, },
@ -361,7 +363,7 @@ describe('include', function() {
it('works when using `where` without `limit`, `skip` or `offset`', it('works when using `where` without `limit`, `skip` or `offset`',
function(done) { function(done) {
User.findOne({ include: { relation: 'posts' }}, function(err, user) { User.findOne({include: {relation: 'posts'}}, function(err, user) {
if (err) return done(err); if (err) return done(err);
var posts = user.posts(); var posts = user.posts();
@ -383,7 +385,7 @@ describe('include', function() {
// --superkhau // --superkhau
Post.dataSource.settings.inqLimit = 2; Post.dataSource.settings.inqLimit = 2;
User.find({ include: { relation: 'posts' }}, function(err, users) { User.find({include: {relation: 'posts'}}, function(err, users) {
if (err) return done(err); if (err) return done(err);
users.length.should.equal(5); users.length.should.equal(5);
@ -397,7 +399,7 @@ describe('include', function() {
it('works when page size is set to 0', function(done) { it('works when page size is set to 0', function(done) {
Post.dataSource.settings.inqLimit = 0; Post.dataSource.settings.inqLimit = 0;
User.find({ include: { relation: 'posts' }}, function(err, users) { User.find({include: {relation: 'posts'}}, function(err, users) {
if (err) return done(err); if (err) return done(err);
users.length.should.equal(5); users.length.should.equal(5);
@ -421,13 +423,13 @@ describe('include', function() {
// --superkhau // --superkhau
it('works when hasOne is called', function(done) { it('works when hasOne is called', function(done) {
User.findOne({ include: { relation: 'profile' }}, function(err, user) { User.findOne({include: {relation: 'profile'}}, function(err, user) {
if (err) return done(err); if (err) return done(err);
user.name.should.equal('User A'); user.name.should.equal('User A');
user.age.should.equal(21); user.age.should.equal(21);
user.id.should.equal(1); user.id.should.equal(1);
profile = user.profile(); var profile = user.profile();
profile.profileName.should.equal('Profile A'); profile.profileName.should.equal('Profile A');
profile.userId.should.equal(1); profile.userId.should.equal(1);
profile.id.should.equal(1); profile.id.should.equal(1);
@ -437,7 +439,7 @@ describe('include', function() {
}); });
it('works when hasMany is called', function(done) { it('works when hasMany is called', function(done) {
User.findOne({ include: { relation: 'posts' }}, function(err, user) { User.findOne({include: {relation: 'posts'}}, function(err, user) {
if (err) return done(); if (err) return done();
user.name.should.equal('User A'); user.name.should.equal('User A');
@ -450,9 +452,9 @@ describe('include', function() {
}); });
it('works when hasManyThrough is called', function(done) { it('works when hasManyThrough is called', function(done) {
Physician = db.define('Physician', { name: String }); var Physician = db.define('Physician', {name: String});
Patient = db.define('Patient', { name: String }); var Patient = db.define('Patient', {name: String});
Appointment = db.define('Appointment', { var Appointment = db.define('Appointment', {
date: { date: {
type: Date, type: Date,
default: function() { default: function() {
@ -460,10 +462,10 @@ describe('include', function() {
}, },
}, },
}); });
Address = db.define('Address', { name: String }); var Address = db.define('Address', {name: String});
Physician.hasMany(Patient, { through: Appointment }); Physician.hasMany(Patient, {through: Appointment});
Patient.hasMany(Physician, { through: Appointment }); Patient.hasMany(Physician, {through: Appointment});
Patient.belongsTo(Address); Patient.belongsTo(Address);
Appointment.belongsTo(Patient); Appointment.belongsTo(Patient);
Appointment.belongsTo(Physician); Appointment.belongsTo(Physician);
@ -471,11 +473,11 @@ describe('include', function() {
db.automigrate(['Physician', 'Patient', 'Appointment', 'Address'], db.automigrate(['Physician', 'Patient', 'Appointment', 'Address'],
function() { function() {
Physician.create(function(err, physician) { Physician.create(function(err, physician) {
physician.patients.create({ name: 'a' }, function(err, patient) { physician.patients.create({name: 'a'}, function(err, patient) {
Address.create({ name: 'z' }, function(err, address) { Address.create({name: 'z'}, function(err, address) {
patient.address(address); patient.address(address);
patient.save(function() { patient.save(function() {
physician.patients({ include: 'address' }, physician.patients({include: 'address'},
function(err, posts) { function(err, posts) {
if (err) return done(err); if (err) return done(err);
@ -496,13 +498,13 @@ describe('include', function() {
}); });
it('works when belongsTo is called', function(done) { it('works when belongsTo is called', function(done) {
Profile.findOne({ include: 'user' }, function(err, profile) { Profile.findOne({include: 'user'}, function(err, profile) {
if (err) return done(err); if (err) return done(err);
profile.profileName.should.equal('Profile A'); profile.profileName.should.equal('Profile A');
profile.userId.should.equal(1); profile.userId.should.equal(1);
profile.id.should.equal(1); profile.id.should.equal(1);
user = profile.user(); var user = profile.user();
user.name.should.equal('User A'); user.name.should.equal('User A');
user.age.should.equal(21); user.age.should.equal(21);
user.id.should.equal(1); user.id.should.equal(1);
@ -515,7 +517,7 @@ describe('include', function() {
it('should fetch Users with include scope on Posts - belongsTo', it('should fetch Users with include scope on Posts - belongsTo',
function(done) { function(done) {
Post.find({ include: { relation: 'author', scope: { fields: ['name'] }}}, Post.find({include: {relation: 'author', scope: {fields: ['name']}}},
function(err, posts) { function(err, posts) {
should.not.exist(err); should.not.exist(err);
should.exist(posts); should.exist(posts);
@ -532,7 +534,7 @@ describe('include', function() {
it('should fetch Users with include scope on Posts - hasMany', function(done) { it('should fetch Users with include scope on Posts - hasMany', function(done) {
User.find({ User.find({
include: { relation: 'posts', scope: { include: {relation: 'posts', scope: {
order: 'title DESC', order: 'title DESC',
}}, }},
}, function(err, users) { }, function(err, users) {
@ -562,8 +564,8 @@ describe('include', function() {
it('should fetch Users with include scope on Passports - hasMany', function(done) { it('should fetch Users with include scope on Passports - hasMany', function(done) {
User.find({ User.find({
include: { relation: 'passports', scope: { include: {relation: 'passports', scope: {
where: { number: '2' }, where: {number: '2'},
}}, }},
}, function(err, users) { }, function(err, users) {
should.not.exist(err); should.not.exist(err);
@ -582,7 +584,7 @@ describe('include', function() {
}); });
it('should fetch User - Posts AND Passports', function(done) { it('should fetch User - Posts AND Passports', function(done) {
User.find({ include: ['posts', 'passports'] }, function(err, users) { User.find({include: ['posts', 'passports']}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
@ -615,12 +617,12 @@ describe('include', function() {
it('should fetch User - Posts AND Passports in relation syntax', it('should fetch User - Posts AND Passports in relation syntax',
function(done) { function(done) {
User.find({ include: [ User.find({include: [
{ relation: 'posts', scope: { {relation: 'posts', scope: {
where: { title: 'Post A' }, where: {title: 'Post A'},
}}, }},
'passports', 'passports',
] }, function(err, users) { ]}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
@ -653,7 +655,7 @@ describe('include', function() {
}); });
it('should not fetch User - AccessTokens', function(done) { it('should not fetch User - AccessTokens', function(done) {
User.find({ include: ['accesstokens'] }, function(err, users) { User.find({include: ['accesstokens']}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
@ -666,8 +668,8 @@ describe('include', function() {
}); });
it('should support hasAndBelongsToMany', function(done) { it('should support hasAndBelongsToMany', function(done) {
Assembly.create({ name: 'car' }, function(err, assembly) { Assembly.create({name: 'car'}, function(err, assembly) {
Part.create({ partNumber: 'engine' }, function(err, part) { Part.create({partNumber: 'engine'}, function(err, part) {
assembly.parts.add(part, function(err, data) { assembly.parts.add(part, function(err, data) {
assembly.parts(function(err, parts) { assembly.parts(function(err, parts) {
should.not.exist(err); should.not.exist(err);
@ -676,9 +678,9 @@ describe('include', function() {
parts[0].partNumber.should.equal('engine'); parts[0].partNumber.should.equal('engine');
// Create a part // Create a part
assembly.parts.create({ partNumber: 'door' }, function(err, part4) { assembly.parts.create({partNumber: 'door'}, function(err, part4) {
Assembly.find({ include: 'parts' }, function(err, assemblies) { Assembly.find({include: 'parts'}, function(err, assemblies) {
assemblies.length.should.equal(1); assemblies.length.should.equal(1);
assemblies[0].parts().length.should.equal(2); assemblies[0].parts().length.should.equal(2);
done(); done();
@ -692,7 +694,7 @@ describe('include', function() {
}); });
it('should fetch User - Profile (HasOne)', function(done) { it('should fetch User - Profile (HasOne)', function(done) {
User.find({ include: ['profile'] }, function(err, users) { User.find({include: ['profile']}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
@ -724,8 +726,8 @@ describe('include', function() {
// Not implemented correctly, see: loopback-datasource-juggler/issues/166 // Not implemented correctly, see: loopback-datasource-juggler/issues/166
// fixed by DB optimization // fixed by DB optimization
it('should support include scope on hasAndBelongsToMany', function(done) { it('should support include scope on hasAndBelongsToMany', function(done) {
Assembly.find({ include: { relation: 'parts', scope: { Assembly.find({include: {relation: 'parts', scope: {
where: { partNumber: 'engine' }, where: {partNumber: 'engine'},
}}}, function(err, assemblies) { }}}, function(err, assemblies) {
assemblies.length.should.equal(1); assemblies.length.should.equal(1);
var parts = assemblies[0].parts(); var parts = assemblies[0].parts();
@ -773,7 +775,7 @@ describe('include', function() {
}); });
it('including belongsTo should make only 2 db calls', function(done) { it('including belongsTo should make only 2 db calls', function(done) {
var self = this; var self = this;
Passport.find({ include: 'owner' }, function(err, passports) { Passport.find({include: 'owner'}, function(err, passports) {
passports.length.should.be.ok; passports.length.should.be.ok;
passports.forEach(function(p) { passports.forEach(function(p) {
p.__cachedRelations.should.have.property('owner'); p.__cachedRelations.should.have.property('owner');
@ -796,11 +798,11 @@ describe('include', function() {
it('including hasManyThrough should make only 3 db calls', function(done) { it('including hasManyThrough should make only 3 db calls', function(done) {
var self = this; var self = this;
Assembly.create([{ name: 'sedan' }, { name: 'hatchback' }, Assembly.create([{name: 'sedan'}, {name: 'hatchback'},
{ name: 'SUV' }], {name: 'SUV'}],
function(err, assemblies) { function(err, assemblies) {
Part.create([{ partNumber: 'engine' }, { partNumber: 'bootspace' }, Part.create([{partNumber: 'engine'}, {partNumber: 'bootspace'},
{ partNumber: 'silencer' }], {partNumber: 'silencer'}],
function(err, parts) { function(err, parts) {
async.each(parts, function(part, next) { async.each(parts, function(part, next) {
async.each(assemblies, function(assembly, next) { async.each(assemblies, function(assembly, next) {
@ -849,7 +851,7 @@ describe('include', function() {
it('including hasMany should make only 2 db calls', function(done) { it('including hasMany should make only 2 db calls', function(done) {
var self = this; var self = this;
User.find({ include: ['posts', 'passports'] }, function(err, users) { User.find({include: ['posts', 'passports']}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
@ -884,9 +886,9 @@ describe('include', function() {
it('should not make n+1 db calls in relation syntax', it('should not make n+1 db calls in relation syntax',
function(done) { function(done) {
var self = this; var self = this;
User.find({ include: [{ relation: 'posts', scope: { User.find({include: [{relation: 'posts', scope: {
where: { title: 'Post A' }, where: {title: 'Post A'},
}}, 'passports'] }, function(err, users) { }}, 'passports']}, function(err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
@ -921,22 +923,22 @@ describe('include', function() {
}); });
it('should support disableInclude for hasAndBelongsToMany', function() { it('should support disableInclude for hasAndBelongsToMany', function() {
var Patient = db.define('Patient', { name: String }); var Patient = db.define('Patient', {name: String});
var Doctor = db.define('Doctor', { name: String }); var Doctor = db.define('Doctor', {name: String});
var DoctorPatient = db.define('DoctorPatient'); var DoctorPatient = db.define('DoctorPatient');
Doctor.hasAndBelongsToMany('patients', { Doctor.hasAndBelongsToMany('patients', {
model: 'Patient', model: 'Patient',
options: { disableInclude: true }, options: {disableInclude: true},
}); });
var doctor; var doctor;
return db.automigrate(['Patient', 'Doctor', 'DoctorPatient']).then(function() { return db.automigrate(['Patient', 'Doctor', 'DoctorPatient']).then(function() {
return Doctor.create({ name: 'Who' }); return Doctor.create({name: 'Who'});
}).then(function(inst) { }).then(function(inst) {
doctor = inst; doctor = inst;
return doctor.patients.create({ name: 'Lazarus' }); return doctor.patients.create({name: 'Lazarus'});
}).then(function() { }).then(function() {
return Doctor.find({ include: ['patients'] }); return Doctor.find({include: ['patients']});
}).then(function(list) { }).then(function(list) {
list.should.have.length(1); list.should.have.length(1);
list[0].toJSON().should.not.have.property('patients'); list[0].toJSON().should.not.have.property('patients');
@ -966,16 +968,16 @@ function setup(done) {
title: String, title: String,
}); });
Passport.belongsTo('owner', { model: User }); Passport.belongsTo('owner', {model: User});
User.hasMany('passports', { foreignKey: 'ownerId' }); User.hasMany('passports', {foreignKey: 'ownerId'});
User.hasMany('posts', { foreignKey: 'userId' }); User.hasMany('posts', {foreignKey: 'userId'});
User.hasMany('accesstokens', { User.hasMany('accesstokens', {
foreignKey: 'userId', foreignKey: 'userId',
options: { disableInclude: true }, options: {disableInclude: true},
}); });
Profile.belongsTo('user', { model: User }); Profile.belongsTo('user', {model: User});
User.hasOne('profile', { foreignKey: 'userId' }); User.hasOne('profile', {foreignKey: 'userId'});
Post.belongsTo('author', { model: User, foreignKey: 'userId' }); Post.belongsTo('author', {model: User, foreignKey: 'userId'});
Assembly = db.define('Assembly', { Assembly = db.define('Assembly', {
name: String, name: String,
@ -998,11 +1000,11 @@ function setup(done) {
clearAndCreate( clearAndCreate(
User, User,
[ [
{ name: 'User A', age: 21 }, {name: 'User A', age: 21},
{ name: 'User B', age: 22 }, {name: 'User B', age: 22},
{ name: 'User C', age: 23 }, {name: 'User C', age: 23},
{ name: 'User D', age: 24 }, {name: 'User D', age: 24},
{ name: 'User E', age: 25 }, {name: 'User E', age: 25},
], ],
function(items) { function(items) {
createdUsers = items; createdUsers = items;
@ -1016,8 +1018,8 @@ function setup(done) {
clearAndCreate( clearAndCreate(
AccessToken, AccessToken,
[ [
{ token: '1', userId: createdUsers[0].id }, {token: '1', userId: createdUsers[0].id},
{ token: '2', userId: createdUsers[1].id }, {token: '2', userId: createdUsers[1].id},
], ],
function(items) {} function(items) {}
); );
@ -1027,10 +1029,10 @@ function setup(done) {
clearAndCreate( clearAndCreate(
Passport, Passport,
[ [
{ number: '1', ownerId: createdUsers[0].id }, {number: '1', ownerId: createdUsers[0].id},
{ number: '2', ownerId: createdUsers[1].id }, {number: '2', ownerId: createdUsers[1].id},
{ number: '3' }, {number: '3'},
{ number: '4', ownerId: createdUsers[2].id }, {number: '4', ownerId: createdUsers[2].id},
], ],
function(items) { function(items) {
createdPassports = items; createdPassports = items;
@ -1043,9 +1045,9 @@ function setup(done) {
clearAndCreate( clearAndCreate(
Profile, Profile,
[ [
{ profileName: 'Profile A', userId: createdUsers[0].id }, {profileName: 'Profile A', userId: createdUsers[0].id},
{ profileName: 'Profile B', userId: createdUsers[1].id }, {profileName: 'Profile B', userId: createdUsers[1].id},
{ profileName: 'Profile Z' }, {profileName: 'Profile Z'},
], ],
function(items) { function(items) {
createdProfiles = items; createdProfiles = items;
@ -1058,11 +1060,11 @@ function setup(done) {
clearAndCreate( clearAndCreate(
Post, Post,
[ [
{ title: 'Post A', userId: createdUsers[0].id }, {title: 'Post A', userId: createdUsers[0].id},
{ title: 'Post B', userId: createdUsers[0].id }, {title: 'Post B', userId: createdUsers[0].id},
{ title: 'Post C', userId: createdUsers[0].id }, {title: 'Post C', userId: createdUsers[0].id},
{ title: 'Post D', userId: createdUsers[1].id }, {title: 'Post D', userId: createdUsers[1].id},
{ title: 'Post E' }, {title: 'Post E'},
], ],
function(items) { function(items) {
createdPosts = items; createdPosts = items;
@ -1099,7 +1101,7 @@ describe('Model instance with included relation .toJSON()', function() {
var db, ChallengerModel, GameParticipationModel, ResultModel; var db, ChallengerModel, GameParticipationModel, ResultModel;
before(function(done) { before(function(done) {
db = new DataSource({ connector: 'memory' }); db = new DataSource({connector: 'memory'});
ChallengerModel = db.createModel('Challenger', ChallengerModel = db.createModel('Challenger',
{ {
name: String, name: String,
@ -1156,25 +1158,25 @@ describe('Model instance with included relation .toJSON()', function() {
}); });
function createChallengers(callback) { function createChallengers(callback) {
ChallengerModel.create([{ name: 'challenger1' }, { name: 'challenger2' }], callback); ChallengerModel.create([{name: 'challenger1'}, {name: 'challenger2'}], callback);
} }
function createGameParticipations(challengers, callback) { function createGameParticipations(challengers, callback) {
GameParticipationModel.create([ GameParticipationModel.create([
{ challengerId: challengers[0].id, date: Date.now() }, {challengerId: challengers[0].id, date: Date.now()},
{ challengerId: challengers[0].id, date: Date.now() }, {challengerId: challengers[0].id, date: Date.now()},
], callback); ], callback);
} }
function createResults(gameParticipations, callback) { function createResults(gameParticipations, callback) {
ResultModel.create([ ResultModel.create([
{ gameParticipationId: gameParticipations[0].id, points: 10 }, {gameParticipationId: gameParticipations[0].id, points: 10},
{ gameParticipationId: gameParticipations[0].id, points: 20 }, {gameParticipationId: gameParticipations[0].id, points: 20},
], callback); ], callback);
} }
it('should recursively serialize objects', function(done) { it('should recursively serialize objects', function(done) {
var filter = { include: { gameParticipations: 'results' }}; var filter = {include: {gameParticipations: 'results'}};
ChallengerModel.find(filter, function(err, challengers) { ChallengerModel.find(filter, function(err, challengers) {
var levelOneInclusion = challengers[0].toJSON().gameParticipations[0]; var levelOneInclusion = challengers[0].toJSON().gameParticipations[0];

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var assert = require('assert'); var assert = require('assert');
var should = require('should'); var should = require('should');
@ -12,8 +13,8 @@ describe('include_util', function() {
describe('#buildOneToOneIdentityMapWithOrigKeys', function() { describe('#buildOneToOneIdentityMapWithOrigKeys', function() {
it('should return an object with keys', function() { it('should return an object with keys', function() {
var objs = [ var objs = [
{ id: 11, letter: 'A' }, {id: 11, letter: 'A'},
{ id: 22, letter: 'B' }, {id: 22, letter: 'B'},
]; ];
var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id'); var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id');
result.get(11).should.be.ok; result.get(11).should.be.ok;
@ -22,10 +23,10 @@ describe('include_util', function() {
it('should overwrite keys in case of collision', function() { it('should overwrite keys in case of collision', function() {
var objs = [ var objs = [
{ id: 11, letter: 'A' }, {id: 11, letter: 'A'},
{ id: 22, letter: 'B' }, {id: 22, letter: 'B'},
{ id: 33, letter: 'C' }, {id: 33, letter: 'C'},
{ id: 11, letter: 'HA!' }, {id: 11, letter: 'HA!'},
]; ];
var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id'); var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id');
@ -39,8 +40,8 @@ describe('include_util', function() {
describe('#buildOneToOneIdentityMapWithOrigKeys', function() { describe('#buildOneToOneIdentityMapWithOrigKeys', function() {
it('should return an object with keys', function() { it('should return an object with keys', function() {
var objs = [ var objs = [
{ id: 11, letter: 'A' }, {id: 11, letter: 'A'},
{ id: 22, letter: 'B' }, {id: 22, letter: 'B'},
]; ];
var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id'); var result = includeUtils.buildOneToOneIdentityMapWithOrigKeys(objs, 'id');
result.get(11).should.be.ok; result.get(11).should.be.ok;
@ -51,8 +52,8 @@ describe('include_util', function() {
describe('#buildOneToManyIdentityMap', function() { describe('#buildOneToManyIdentityMap', function() {
it('should return an object with keys', function() { it('should return an object with keys', function() {
var objs = [ var objs = [
{ id: 11, letter: 'A' }, {id: 11, letter: 'A'},
{ id: 22, letter: 'B' }, {id: 22, letter: 'B'},
]; ];
var result = includeUtils.buildOneToManyIdentityMapWithOrigKeys(objs, 'id'); var result = includeUtils.buildOneToManyIdentityMapWithOrigKeys(objs, 'id');
result.exist(11).should.be.true; result.exist(11).should.be.true;
@ -61,10 +62,10 @@ describe('include_util', function() {
it('should collect keys in case of collision', function() { it('should collect keys in case of collision', function() {
var objs = [ var objs = [
{ 'fk_id': 11, letter: 'A' }, {'fk_id': 11, letter: 'A'},
{ 'fk_id': 22, letter: 'B' }, {'fk_id': 22, letter: 'B'},
{ 'fk_id': 33, letter: 'C' }, {'fk_id': 33, letter: 'C'},
{ 'fk_id': 11, letter: 'HA!' }, {'fk_id': 11, letter: 'HA!'},
]; ];
var result = includeUtils.buildOneToManyIdentityMapWithOrigKeys(objs, 'fk_id'); var result = includeUtils.buildOneToManyIdentityMapWithOrigKeys(objs, 'fk_id');
@ -90,11 +91,11 @@ describe('KVMap', function() {
map.set('name', 'Alex'); map.set('name', 'Alex');
map.set(true, 'male'); map.set(true, 'male');
map.set(false, false); map.set(false, false);
map.set({ isTrue: 'yes' }, 25); map.set({isTrue: 'yes'}, 25);
map.get('name').should.be.equal('Alex'); map.get('name').should.be.equal('Alex');
map.get(true).should.be.equal('male'); map.get(true).should.be.equal('male');
map.get(false).should.be.equal(false); map.get(false).should.be.equal(false);
map.get({ isTrue: 'yes' }).should.be.equal(25); map.get({isTrue: 'yes'}).should.be.equal(25);
}); });
it('should not allow to get values with [] operator', function() { it('should not allow to get values with [] operator', function() {
var map = new includeUtils.KVMap(); var map = new includeUtils.KVMap();

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
module.exports = require('should'); module.exports = require('should');
/* /*

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var assert = require('assert'); var assert = require('assert');
var ModelBuilder = require('..').ModelBuilder; var ModelBuilder = require('..').ModelBuilder;
var DataSource = require('../').DataSource; var DataSource = require('../').DataSource;
@ -23,8 +24,8 @@ var json = {
}, },
friends: ['John', 'Mary'], friends: ['John', 'Mary'],
emails: [ emails: [
{ label: 'work', id: 'x@sample.com' }, {label: 'work', id: 'x@sample.com'},
{ label: 'home', id: 'x@home.com' }, {label: 'home', id: 'x@home.com'},
], ],
tags: [], tags: [],
}; };
@ -60,7 +61,7 @@ describe('Introspection of model definitions from JSON', function() {
}); });
it('should return a schema for object', function() { it('should return a schema for object', function() {
var json = { a: 'str', b: 0, c: true }; var json = {a: 'str', b: 0, c: true};
var type = introspectType(json); var type = introspectType(json);
assert.equal(type.a, 'string'); assert.equal(type.a, 'string');
assert.equal(type.b, 'number'); assert.equal(type.b, 'number');
@ -68,7 +69,7 @@ describe('Introspection of model definitions from JSON', function() {
}); });
it('should handle nesting objects', function() { it('should handle nesting objects', function() {
var json = { a: 'str', b: 0, c: true, d: { x: 10, y: 5 }}; var json = {a: 'str', b: 0, c: true, d: {x: 10, y: 5}};
var type = introspectType(json); var type = introspectType(json);
assert.equal(type.a, 'string'); assert.equal(type.a, 'string');
assert.equal(type.b, 'number'); assert.equal(type.b, 'number');
@ -78,7 +79,7 @@ describe('Introspection of model definitions from JSON', function() {
}); });
it('should handle nesting arrays', function() { it('should handle nesting arrays', function() {
var json = { a: 'str', b: 0, c: true, d: [1, 2] }; var json = {a: 'str', b: 0, c: true, d: [1, 2]};
var type = introspectType(json); var type = introspectType(json);
assert.equal(type.a, 'string'); assert.equal(type.a, 'string');
assert.equal(type.b, 'number'); assert.equal(type.b, 'number');
@ -92,7 +93,7 @@ describe('Introspection of model definitions from JSON', function() {
var schema = introspectType(json); var schema = introspectType(json);
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var Model = builder.define('MyModel', schema, { idInjection: false }); var Model = builder.define('MyModel', schema, {idInjection: false});
// FIXME: [rfeng] The constructor mutates the arguments // FIXME: [rfeng] The constructor mutates the arguments
var obj = new Model(json); var obj = new Model(json);
@ -107,7 +108,7 @@ describe('Introspection of model definitions from JSON', function() {
var copy = traverse(json).clone(); var copy = traverse(json).clone();
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var Model = builder.buildModelFromInstance('MyModel', copy, { idInjection: false }); var Model = builder.buildModelFromInstance('MyModel', copy, {idInjection: false});
var obj = new Model(json); var obj = new Model(json);
obj = obj.toObject(); obj = obj.toObject();
@ -120,7 +121,7 @@ describe('Introspection of model definitions from JSON', function() {
var builder = new DataSource('memory'); var builder = new DataSource('memory');
var Model = builder.buildModelFromInstance('MyModel', copy, var Model = builder.buildModelFromInstance('MyModel', copy,
{ idInjection: false }); {idInjection: false});
assert.equal(Model.dataSource, builder); assert.equal(Model.dataSource, builder);

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var Schema = require('../').Schema; var Schema = require('../').Schema;
@ -14,7 +15,7 @@ describe('JSON property', function() {
it('should be defined', function() { it('should be defined', function() {
dataSource = getSchema(); dataSource = getSchema();
Model = dataSource.define('Model', { propertyName: ModelBuilder.JSON }); Model = dataSource.define('Model', {propertyName: ModelBuilder.JSON});
var m = new Model; var m = new Model;
(new Boolean('propertyName' in m)).should.eql(true); (new Boolean('propertyName' in m)).should.eql(true);
should.not.exist(m.propertyName); should.not.exist(m.propertyName);
@ -30,7 +31,7 @@ describe('JSON property', function() {
it('should accept object in setter and return object', function() { it('should accept object in setter and return object', function() {
var m = new Model; var m = new Model;
m.propertyName = { 'foo': 'bar' }; m.propertyName = {'foo': 'bar'};
m.propertyName.should.be.an.Object; m.propertyName.should.be.an.Object;
m.propertyName.foo.should.equal('bar'); m.propertyName.foo.should.equal('bar');
}); });

View File

@ -1,9 +1,10 @@
'use strict';
var kvMemory = require('../lib/connectors/kv-memory'); var kvMemory = require('../lib/connectors/kv-memory');
var DataSource = require('..').DataSource; var DataSource = require('..').DataSource;
describe('KeyValue-Memory connector', function() { describe('KeyValue-Memory connector', function() {
var dataSourceFactory = function() { var dataSourceFactory = function() {
return new DataSource({ connector: kvMemory }); return new DataSource({connector: kvMemory});
}; };
require('./kvao.suite')(dataSourceFactory); require('./kvao.suite')(dataSourceFactory);

View File

@ -29,9 +29,9 @@ module.exports = function(dataSourceFactory, connectorCapabilities) {
}); });
it('works for Object values', function() { it('works for Object values', function() {
return CacheItem.set('a-key', { a: 1, b: 2 }) return CacheItem.set('a-key', {a: 1, b: 2})
.then(function() { return CacheItem.get('a-key'); }) .then(function() { return CacheItem.get('a-key'); })
.then(function(value) { value.should.eql({ a: 1, b: 2 }); }); .then(function(value) { value.should.eql({a: 1, b: 2}); });
}); });
it('works for Buffer values', function() { it('works for Buffer values', function() {
@ -68,7 +68,7 @@ module.exports = function(dataSourceFactory, connectorCapabilities) {
}); });
it('honours options.ttl', function() { it('honours options.ttl', function() {
return CacheItem.set('a-key', 'a-value', { ttl: 10 }) return CacheItem.set('a-key', 'a-value', {ttl: 10})
.delay(20) .delay(20)
.then(function() { return CacheItem.get('a-key'); }) .then(function() { return CacheItem.get('a-key'); })
.then(function(value) { should.equal(value, null); }); .then(function(value) { should.equal(value, null); });
@ -90,7 +90,7 @@ module.exports = function(dataSourceFactory, connectorCapabilities) {
describe('set', function() { describe('set', function() {
it('resets TTL timer', function() { it('resets TTL timer', function() {
return CacheItem.set('a-key', 'a-value', { ttl: 10 }) return CacheItem.set('a-key', 'a-value', {ttl: 10})
.then(function() { .then(function() {
return CacheItem.set('a-key', 'another-value'); // no TTL return CacheItem.set('a-key', 'another-value'); // no TTL
}) })

View File

@ -83,19 +83,19 @@ module.exports = function(dataSourceFactory, connectorCapabilities) {
}); });
it('supports "?" operator', function() { it('supports "?" operator', function() {
return CacheItem.sortedKeys({ match: 'h?llo' }).then(function(keys) { return CacheItem.sortedKeys({match: 'h?llo'}).then(function(keys) {
should(keys).eql(['hallo', 'hello', 'hxllo']); should(keys).eql(['hallo', 'hello', 'hxllo']);
}); });
}); });
it('supports "*" operator', function() { it('supports "*" operator', function() {
return CacheItem.sortedKeys({ match: 'h*llo' }).then(function(keys) { return CacheItem.sortedKeys({match: 'h*llo'}).then(function(keys) {
should(keys).eql(['hallo', 'heeello', 'hello', 'hllo', 'hxllo']); should(keys).eql(['hallo', 'heeello', 'hello', 'hllo', 'hxllo']);
}); });
}); });
it('handles no matches found', function() { it('handles no matches found', function() {
return CacheItem.sortedKeys({ match: 'not-found' }) return CacheItem.sortedKeys({match: 'not-found'})
.then(function(keys) { .then(function(keys) {
should(keys).eql([]); should(keys).eql([]);
}); });

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var loopbackData = require('../'); var loopbackData = require('../');

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var jdb = require('../'); var jdb = require('../');
var DataSource = jdb.DataSource; var DataSource = jdb.DataSource;
var path = require('path'); var path = require('path');
@ -64,7 +65,7 @@ describe('Memory connector', function() {
it('should persist create', function(done) { it('should persist create', function(done) {
var count = 0; var count = 0;
async.eachSeries(['John1', 'John2', 'John3'], function(item, cb) { async.eachSeries(['John1', 'John2', 'John3'], function(item, cb) {
User.create({ name: item }, function(err, result) { User.create({name: item}, function(err, result) {
ids.push(result.id); ids.push(result.id);
count++; count++;
readModels(function(err, json) { readModels(function(err, json) {
@ -92,7 +93,7 @@ describe('Memory connector', function() {
}); });
it('should persist upsert', function(done) { it('should persist upsert', function(done) {
User.upsert({ id: ids[1], name: 'John' }, function(err, result) { User.upsert({id: ids[1], name: 'John'}, function(err, result) {
if (err) { if (err) {
return done(err); return done(err);
} }
@ -110,7 +111,7 @@ describe('Memory connector', function() {
}); });
it('should persist update', function(done) { it('should persist update', function(done) {
User.update({ id: ids[1] }, { name: 'John1' }, User.update({id: ids[1]}, {name: 'John1'},
function(err, result) { function(err, result) {
if (err) { if (err) {
return done(err); return done(err);
@ -145,13 +146,13 @@ describe('Memory connector', function() {
}); });
var User = ds.define('User', { var User = ds.define('User', {
seq: { type: Number, index: true }, seq: {type: Number, index: true},
name: { type: String, index: true, sort: true }, name: {type: String, index: true, sort: true},
email: { type: String, index: true }, email: {type: String, index: true},
birthday: { type: Date, index: true }, birthday: {type: Date, index: true},
role: { type: String, index: true }, role: {type: String, index: true},
order: { type: Number, index: true, sort: true }, order: {type: Number, index: true, sort: true},
vip: { type: Boolean }, vip: {type: Boolean},
address: { address: {
street: String, street: String,
city: String, city: String,
@ -167,7 +168,7 @@ describe('Memory connector', function() {
before(seed); before(seed);
it('should allow to find using like', function(done) { it('should allow to find using like', function(done) {
User.find({ where: { name: { like: '%St%' }}}, function(err, posts) { User.find({where: {name: {like: '%St%'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 2); posts.should.have.property('length', 2);
done(); done();
@ -175,7 +176,7 @@ describe('Memory connector', function() {
}); });
it('should allow to find using like with regexp', function(done) { it('should allow to find using like with regexp', function(done) {
User.find({ where: { name: { like: /.*St.*/ }}}, function(err, posts) { User.find({where: {name: {like: /.*St.*/}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 2); posts.should.have.property('length', 2);
done(); done();
@ -183,7 +184,7 @@ describe('Memory connector', function() {
}); });
it('should support like for no match', function(done) { it('should support like for no match', function(done) {
User.find({ where: { name: { like: 'M%XY' }}}, function(err, posts) { User.find({where: {name: {like: 'M%XY'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 0); posts.should.have.property('length', 0);
done(); done();
@ -191,7 +192,7 @@ describe('Memory connector', function() {
}); });
it('should allow to find using nlike', function(done) { it('should allow to find using nlike', function(done) {
User.find({ where: { name: { nlike: '%St%' }}}, function(err, posts) { User.find({where: {name: {nlike: '%St%'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 4); posts.should.have.property('length', 4);
done(); done();
@ -199,7 +200,7 @@ describe('Memory connector', function() {
}); });
it('should allow to find using nlike with regexp', function(done) { it('should allow to find using nlike with regexp', function(done) {
User.find({ where: { name: { nlike: /.*St.*/ }}}, function(err, posts) { User.find({where: {name: {nlike: /.*St.*/}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 4); posts.should.have.property('length', 4);
done(); done();
@ -207,7 +208,7 @@ describe('Memory connector', function() {
}); });
it('should support nlike for no match', function(done) { it('should support nlike for no match', function(done) {
User.find({ where: { name: { nlike: 'M%XY' }}}, function(err, posts) { User.find({where: {name: {nlike: 'M%XY'}}}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts.should.have.property('length', 6); posts.should.have.property('length', 6);
done(); done();
@ -215,56 +216,56 @@ describe('Memory connector', function() {
}); });
it('should throw if the like value is not string or regexp', function(done) { it('should throw if the like value is not string or regexp', function(done) {
User.find({ where: { name: { like: 123 }}}, function(err, posts) { User.find({where: {name: {like: 123}}}, function(err, posts) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('should throw if the nlike value is not string or regexp', function(done) { it('should throw if the nlike value is not string or regexp', function(done) {
User.find({ where: { name: { nlike: 123 }}}, function(err, posts) { User.find({where: {name: {nlike: 123}}}, function(err, posts) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('should throw if the inq value is not an array', function(done) { it('should throw if the inq value is not an array', function(done) {
User.find({ where: { name: { inq: '12' }}}, function(err, posts) { User.find({where: {name: {inq: '12'}}}, function(err, posts) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('should throw if the nin value is not an array', function(done) { it('should throw if the nin value is not an array', function(done) {
User.find({ where: { name: { nin: '12' }}}, function(err, posts) { User.find({where: {name: {nin: '12'}}}, function(err, posts) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('should throw if the between value is not an array', function(done) { it('should throw if the between value is not an array', function(done) {
User.find({ where: { name: { between: '12' }}}, function(err, posts) { User.find({where: {name: {between: '12'}}}, function(err, posts) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('should throw if the between value is not an array of length 2', function(done) { it('should throw if the between value is not an array of length 2', function(done) {
User.find({ where: { name: { between: ['12'] }}}, function(err, posts) { User.find({where: {name: {between: ['12']}}}, function(err, posts) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('should successfully extract 5 users from the db', function(done) { it('should successfully extract 5 users from the db', function(done) {
User.find({ where: { seq: { between: [1, 5] }}}, function(err, users) { User.find({where: {seq: {between: [1, 5]}}}, function(err, users) {
should(users.length).be.equal(5); should(users.length).be.equal(5);
done(); done();
}); });
}); });
it('should successfully extract 1 user (Lennon) from the db', function(done) { it('should successfully extract 1 user (Lennon) from the db', function(done) {
User.find({ where: { birthday: { between: [new Date(1970, 0), new Date(1990, 0)] }}}, User.find({where: {birthday: {between: [new Date(1970, 0), new Date(1990, 0)]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(1); should(users.length).be.equal(1);
should(users[0].name).be.equal('John Lennon'); should(users[0].name).be.equal('John Lennon');
@ -273,7 +274,7 @@ describe('Memory connector', function() {
}); });
it('should successfully extract 2 users from the db', function(done) { it('should successfully extract 2 users from the db', function(done) {
User.find({ where: { birthday: { between: [new Date(1940, 0), new Date(1990, 0)] }}}, User.find({where: {birthday: {between: [new Date(1940, 0), new Date(1990, 0)]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(2); should(users.length).be.equal(2);
done(); done();
@ -281,7 +282,7 @@ describe('Memory connector', function() {
}); });
it('should successfully extract 2 users using implied and', function(done) { it('should successfully extract 2 users using implied and', function(done) {
User.find({ where: { role: 'lead', vip: true }}, function(err, users) { User.find({where: {role: 'lead', vip: true}}, function(err, users) {
should(users.length).be.equal(2); should(users.length).be.equal(2);
should(users[0].name).be.equal('John Lennon'); should(users[0].name).be.equal('John Lennon');
should(users[1].name).be.equal('Paul McCartney'); should(users[1].name).be.equal('Paul McCartney');
@ -290,9 +291,9 @@ describe('Memory connector', function() {
}); });
it('should successfully extract 2 users using implied and & and', function(done) { it('should successfully extract 2 users using implied and & and', function(done) {
User.find({ where: { User.find({where: {
name: 'John Lennon', name: 'John Lennon',
and: [{ role: 'lead' }, { vip: true }], and: [{role: 'lead'}, {vip: true}],
}}, function(err, users) { }}, function(err, users) {
should(users.length).be.equal(1); should(users.length).be.equal(1);
should(users[0].name).be.equal('John Lennon'); should(users[0].name).be.equal('John Lennon');
@ -301,8 +302,8 @@ describe('Memory connector', function() {
}); });
it('should successfully extract 2 users using date range', function(done) { it('should successfully extract 2 users using date range', function(done) {
User.find({ where: { birthday: { between: User.find({where: {birthday: {between:
[new Date(1940, 0).toISOString(), new Date(1990, 0).toISOString()] }}}, [new Date(1940, 0).toISOString(), new Date(1990, 0).toISOString()]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(2); should(users.length).be.equal(2);
done(); done();
@ -310,7 +311,7 @@ describe('Memory connector', function() {
}); });
it('should successfully extract 0 user from the db', function(done) { it('should successfully extract 0 user from the db', function(done) {
User.find({ where: { birthday: { between: [new Date(1990, 0), Date.now()] }}}, User.find({where: {birthday: {between: [new Date(1990, 0), Date.now()]}}},
function(err, users) { function(err, users) {
should(users.length).be.equal(0); should(users.length).be.equal(0);
done(); done();
@ -349,7 +350,7 @@ describe('Memory connector', function() {
it('should successfully extract 5 users matching a neq filter over array values', function(done) { it('should successfully extract 5 users matching a neq filter over array values', function(done) {
User.find({ User.find({
where: { where: {
children: { neq: 'Dhani' }, children: {neq: 'Dhani'},
}, },
}, function(err, users) { }, function(err, users) {
should.not.exist(err); should.not.exist(err);
@ -360,7 +361,7 @@ describe('Memory connector', function() {
it('should successfully extract 3 users with inq', function(done) { it('should successfully extract 3 users with inq', function(done) {
User.find({ User.find({
where: { seq: { inq: [0, 1, 5] }}, where: {seq: {inq: [0, 1, 5]}},
}, function(err, users) { }, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(3); users.length.should.be.equal(3);
@ -370,7 +371,7 @@ describe('Memory connector', function() {
it('should successfully extract 4 users with nin', function(done) { it('should successfully extract 4 users with nin', function(done) {
User.find({ User.find({
where: { seq: { nin: [2, 3] }}, where: {seq: {nin: [2, 3]}},
}, function(err, users) { }, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(4); users.length.should.be.equal(4);
@ -379,7 +380,7 @@ describe('Memory connector', function() {
}); });
it('should count using date string', function(done) { it('should count using date string', function(done) {
User.count({ birthday: { lt: new Date(1990, 0).toISOString() }}, User.count({birthday: {lt: new Date(1990, 0).toISOString()}},
function(err, count) { function(err, count) {
should(count).be.equal(2); should(count).be.equal(2);
done(); done();
@ -387,7 +388,7 @@ describe('Memory connector', function() {
}); });
it('should support order with multiple fields', function(done) { it('should support order with multiple fields', function(done) {
User.find({ order: 'vip ASC, seq DESC' }, function(err, posts) { User.find({order: 'vip ASC, seq DESC'}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts[0].seq.should.be.eql(4); posts[0].seq.should.be.eql(4);
posts[1].seq.should.be.eql(3); posts[1].seq.should.be.eql(3);
@ -396,7 +397,7 @@ describe('Memory connector', function() {
}); });
it('should sort undefined values to the end when ordered DESC', function(done) { it('should sort undefined values to the end when ordered DESC', function(done) {
User.find({ order: 'vip ASC, order DESC' }, function(err, posts) { User.find({order: 'vip ASC, order DESC'}, function(err, posts) {
should.not.exist(err); should.not.exist(err);
posts[4].seq.should.be.eql(1); posts[4].seq.should.be.eql(1);
@ -406,14 +407,14 @@ describe('Memory connector', function() {
}); });
it('should throw if order has wrong direction', function(done) { it('should throw if order has wrong direction', function(done) {
User.find({ order: 'seq ABC' }, function(err, posts) { User.find({order: 'seq ABC'}, function(err, posts) {
should.exist(err); should.exist(err);
done(); done();
}); });
}); });
it('should support neq operator for number', function(done) { it('should support neq operator for number', function(done) {
User.find({ where: { seq: { neq: 4 }}}, function(err, users) { User.find({where: {seq: {neq: 4}}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(5); users.length.should.be.equal(5);
for (var i = 0; i < users.length; i++) { for (var i = 0; i < users.length; i++) {
@ -424,7 +425,7 @@ describe('Memory connector', function() {
}); });
it('should support neq operator for string', function(done) { it('should support neq operator for string', function(done) {
User.find({ where: { role: { neq: 'lead' }}}, function(err, users) { User.find({where: {role: {neq: 'lead'}}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(4); users.length.should.be.equal(4);
for (var i = 0; i < users.length; i++) { for (var i = 0; i < users.length; i++) {
@ -437,7 +438,7 @@ describe('Memory connector', function() {
}); });
it('should support neq operator for null', function(done) { it('should support neq operator for null', function(done) {
User.find({ where: { role: { neq: null }}}, function(err, users) { User.find({where: {role: {neq: null}}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(2); users.length.should.be.equal(2);
for (var i = 0; i < users.length; i++) { for (var i = 0; i < users.length; i++) {
@ -449,7 +450,7 @@ describe('Memory connector', function() {
it('should work when a regex is provided without the regexp operator', it('should work when a regex is provided without the regexp operator',
function(done) { function(done) {
User.find({ where: { name: /John.*/i }}, function(err, users) { User.find({where: {name: /John.*/i}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.equal(1); users.length.should.equal(1);
users[0].name.should.equal('John Lennon'); users[0].name.should.equal('John Lennon');
@ -458,7 +459,7 @@ describe('Memory connector', function() {
}); });
it('should support the regexp operator with regex strings', function(done) { it('should support the regexp operator with regex strings', function(done) {
User.find({ where: { name: { regexp: '^J' }}}, function(err, users) { User.find({where: {name: {regexp: '^J'}}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.equal(1); users.length.should.equal(1);
users[0].name.should.equal('John Lennon'); users[0].name.should.equal('John Lennon');
@ -467,7 +468,7 @@ describe('Memory connector', function() {
}); });
it('should support the regexp operator with regex literals', function(done) { it('should support the regexp operator with regex literals', function(done) {
User.find({ where: { name: { regexp: /^J/ }}}, function(err, users) { User.find({where: {name: {regexp: /^J/}}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.equal(1); users.length.should.equal(1);
users[0].name.should.equal('John Lennon'); users[0].name.should.equal('John Lennon');
@ -476,7 +477,7 @@ describe('Memory connector', function() {
}); });
it('should support the regexp operator with regex objects', function(done) { it('should support the regexp operator with regex objects', function(done) {
User.find({ where: { name: { regexp: new RegExp(/^J/) }}}, function(err, User.find({where: {name: {regexp: new RegExp(/^J/)}}}, function(err,
users) { users) {
should.not.exist(err); should.not.exist(err);
users.length.should.equal(1); users.length.should.equal(1);
@ -486,7 +487,7 @@ describe('Memory connector', function() {
}); });
it('should support nested property in query', function(done) { it('should support nested property in query', function(done) {
User.find({ where: { 'address.city': 'San Jose' }}, function(err, users) { User.find({where: {'address.city': 'San Jose'}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(1); users.length.should.be.equal(1);
for (var i = 0; i < users.length; i++) { for (var i = 0; i < users.length; i++) {
@ -497,7 +498,7 @@ describe('Memory connector', function() {
}); });
it('should support nested property with regex over arrays in query', function(done) { it('should support nested property with regex over arrays in query', function(done) {
User.find({ where: { 'friends.name': { regexp: /^Ringo/ }}}, function(err, users) { User.find({where: {'friends.name': {regexp: /^Ringo/}}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(2); users.length.should.be.equal(2);
users[0].name.should.be.equal('John Lennon'); users[0].name.should.be.equal('John Lennon');
@ -507,7 +508,7 @@ describe('Memory connector', function() {
}); });
it('should support nested property with gt in query', function(done) { it('should support nested property with gt in query', function(done) {
User.find({ where: { 'address.city': { gt: 'San' }}}, function(err, users) { User.find({where: {'address.city': {gt: 'San'}}}, function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(2); users.length.should.be.equal(2);
for (var i = 0; i < users.length; i++) { for (var i = 0; i < users.length; i++) {
@ -518,7 +519,7 @@ describe('Memory connector', function() {
}); });
it('should support nested property for order in query', function(done) { it('should support nested property for order in query', function(done) {
User.find({ where: { 'address.state': 'CA' }, order: 'address.city DESC' }, User.find({where: {'address.state': 'CA'}, order: 'address.city DESC'},
function(err, users) { function(err, users) {
should.not.exist(err); should.not.exist(err);
users.length.should.be.equal(2); users.length.should.be.equal(2);
@ -529,8 +530,8 @@ describe('Memory connector', function() {
}); });
it('should deserialize values after saving in upsert', function(done) { it('should deserialize values after saving in upsert', function(done) {
User.findOne({ where: { seq: 1 }}, function(err, paul) { User.findOne({where: {seq: 1}}, function(err, paul) {
User.updateOrCreate({ id: paul.id, name: 'Sir Paul McCartney' }, User.updateOrCreate({id: paul.id, name: 'Sir Paul McCartney'},
function(err, sirpaul) { function(err, sirpaul) {
should.not.exist(err); should.not.exist(err);
sirpaul.birthday.should.be.instanceOf(Date); sirpaul.birthday.should.be.instanceOf(Date);
@ -557,9 +558,9 @@ describe('Memory connector', function() {
zipCode: '95131', zipCode: '95131',
}, },
friends: [ friends: [
{ name: 'Paul McCartney' }, {name: 'Paul McCartney'},
{ name: 'George Harrison' }, {name: 'George Harrison'},
{ name: 'Ringo Starr' }, {name: 'Ringo Starr'},
], ],
children: ['Sean', 'Julian'], children: ['Sean', 'Julian'],
}, },
@ -578,16 +579,16 @@ describe('Memory connector', function() {
zipCode: '94065', zipCode: '94065',
}, },
friends: [ friends: [
{ name: 'John Lennon' }, {name: 'John Lennon'},
{ name: 'George Harrison' }, {name: 'George Harrison'},
{ name: 'Ringo Starr' }, {name: 'Ringo Starr'},
], ],
children: ['Stella', 'Mary', 'Heather', 'Beatrice', 'James'], children: ['Stella', 'Mary', 'Heather', 'Beatrice', 'James'],
}, },
{ seq: 2, name: 'George Harrison', order: 5, vip: false, children: ['Dhani'] }, {seq: 2, name: 'George Harrison', order: 5, vip: false, children: ['Dhani']},
{ seq: 3, name: 'Ringo Starr', order: 6, vip: false }, {seq: 3, name: 'Ringo Starr', order: 6, vip: false},
{ seq: 4, name: 'Pete Best', order: 4, children: [] }, {seq: 4, name: 'Pete Best', order: 4, children: []},
{ seq: 5, name: 'Stuart Sutcliffe', order: 3, vip: true }, {seq: 5, name: 'Stuart Sutcliffe', order: 3, vip: true},
]; ];
async.series([ async.series([
@ -611,32 +612,32 @@ describe('Memory connector', function() {
var Tool = ds.createModel('Tool', { var Tool = ds.createModel('Tool', {
name: String, name: String,
}, { memory: { collection: 'Product' }}); }, {memory: {collection: 'Product'}});
var Widget = ds.createModel('Widget', { var Widget = ds.createModel('Widget', {
name: String, name: String,
}, { memory: { collection: 'Product' }}); }, {memory: {collection: 'Product'}});
ds.connector.getCollection('Tool').should.equal('Product'); ds.connector.getCollection('Tool').should.equal('Product');
ds.connector.getCollection('Widget').should.equal('Product'); ds.connector.getCollection('Widget').should.equal('Product');
async.series([ async.series([
function(next) { function(next) {
Tool.create({ name: 'Tool A' }, next); Tool.create({name: 'Tool A'}, next);
}, },
function(next) { function(next) {
Tool.create({ name: 'Tool B' }, next); Tool.create({name: 'Tool B'}, next);
}, },
function(next) { function(next) {
Widget.create({ name: 'Widget A' }, next); Widget.create({name: 'Widget A'}, next);
}, },
], function(err) { ], function(err) {
Product.find(function(err, products) { Product.find(function(err, products) {
should.not.exist(err); should.not.exist(err);
products.should.have.length(3); products.should.have.length(3);
products[0].toObject().should.eql({ name: 'Tool A', id: 1 }); products[0].toObject().should.eql({name: 'Tool A', id: 1});
products[1].toObject().should.eql({ name: 'Tool B', id: 2 }); products[1].toObject().should.eql({name: 'Tool B', id: 2});
products[2].toObject().should.eql({ name: 'Widget A', id: 3 }); products[2].toObject().should.eql({name: 'Widget A', id: 3});
done(); done();
}); });
}); });
@ -725,7 +726,7 @@ describe('Memory connector', function() {
describe('findOrCreate', function() { describe('findOrCreate', function() {
var ds, Cars; var ds, Cars;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
Cars = ds.define('Cars', { Cars = ds.define('Cars', {
color: String, color: String,
}); });
@ -734,8 +735,8 @@ describe('Memory connector', function() {
it('should create a specific object once and in the subsequent calls it should find it', function(done) { it('should create a specific object once and in the subsequent calls it should find it', function(done) {
var creationNum = 0; var creationNum = 0;
async.times(100, function(n, next) { async.times(100, function(n, next) {
var initialData = { color: 'white' }; var initialData = {color: 'white'};
var query = { 'where': initialData }; var query = {'where': initialData};
Cars.findOrCreate(query, initialData, function(err, car, created) { Cars.findOrCreate(query, initialData, function(err, car, created) {
if (created) creationNum++; if (created) creationNum++;
next(err, car); next(err, car);
@ -868,7 +869,7 @@ describe('Memory connector', function() {
}); });
describe('Optimized connector', function() { describe('Optimized connector', function() {
var ds = new DataSource({ connector: Memory }); var ds = new DataSource({connector: Memory});
// optimized methods // optimized methods
ds.connector.findOrCreate = function(model, query, data, callback) { ds.connector.findOrCreate = function(model, query, data, callback) {
@ -880,23 +881,23 @@ describe('Optimized connector', function() {
}.bind(this)); }.bind(this));
}; };
require('./persistence-hooks.suite')(ds, should, { replaceOrCreateReportsNewInstance: true }); require('./persistence-hooks.suite')(ds, should, {replaceOrCreateReportsNewInstance: true});
}); });
describe('Unoptimized connector', function() { describe('Unoptimized connector', function() {
var ds = new DataSource({ connector: Memory }); var ds = new DataSource({connector: Memory});
// disable optimized methods // disable optimized methods
ds.connector.updateOrCreate = false; ds.connector.updateOrCreate = false;
ds.connector.findOrCreate = false; ds.connector.findOrCreate = false;
require('./persistence-hooks.suite')(ds, should, { replaceOrCreateReportsNewInstance: true }); require('./persistence-hooks.suite')(ds, should, {replaceOrCreateReportsNewInstance: true});
}); });
describe('Memory connector with options', function() { describe('Memory connector with options', function() {
var ds, savedOptions = {}, Post; var ds, savedOptions = {}, Post;
before(function() { before(function() {
ds = new DataSource({ connector: 'memory' }); ds = new DataSource({connector: 'memory'});
ds.connector.create = function(model, data, options, cb) { ds.connector.create = function(model, data, options, cb) {
savedOptions.create = options; savedOptions.create = options;
process.nextTick(function() { process.nextTick(function() {
@ -907,14 +908,14 @@ describe('Memory connector with options', function() {
ds.connector.update = function(model, where, data, options, cb) { ds.connector.update = function(model, where, data, options, cb) {
savedOptions.update = options; savedOptions.update = options;
process.nextTick(function() { process.nextTick(function() {
cb(null, { count: 1 }); cb(null, {count: 1});
}); });
}; };
ds.connector.all = function(model, filter, options, cb) { ds.connector.all = function(model, filter, options, cb) {
savedOptions.find = options; savedOptions.find = options;
process.nextTick(function() { process.nextTick(function() {
cb(null, [{ title: 't1', content: 'c1' }]); cb(null, [{title: 't1', content: 'c1'}]);
}); });
}; };
@ -925,15 +926,15 @@ describe('Memory connector with options', function() {
}); });
it('should receive options from the find method', function(done) { it('should receive options from the find method', function(done) {
var opts = { transaction: 'tx1' }; var opts = {transaction: 'tx1'};
Post.find({ where: { title: 't1' }}, opts, function(err, p) { Post.find({where: {title: 't1'}}, opts, function(err, p) {
savedOptions.find.should.be.eql(opts); savedOptions.find.should.be.eql(opts);
done(err); done(err);
}); });
}); });
it('should receive options from the find method', function(done) { it('should receive options from the find method', function(done) {
var opts = { transaction: 'tx2' }; var opts = {transaction: 'tx2'};
Post.find({}, opts, function(err, p) { Post.find({}, opts, function(err, p) {
savedOptions.find.should.be.eql(opts); savedOptions.find.should.be.eql(opts);
done(err); done(err);
@ -941,7 +942,7 @@ describe('Memory connector with options', function() {
}); });
it('should treat first object arg as filter for find', function(done) { it('should treat first object arg as filter for find', function(done) {
var filter = { title: 't1' }; var filter = {title: 't1'};
Post.find(filter, function(err, p) { Post.find(filter, function(err, p) {
savedOptions.find.should.be.eql({}); savedOptions.find.should.be.eql({});
done(err); done(err);
@ -949,16 +950,16 @@ describe('Memory connector with options', function() {
}); });
it('should receive options from the create method', function(done) { it('should receive options from the create method', function(done) {
var opts = { transaction: 'tx3' }; var opts = {transaction: 'tx3'};
Post.create({ title: 't1', content: 'c1' }, opts, function(err, p) { Post.create({title: 't1', content: 'c1'}, opts, function(err, p) {
savedOptions.create.should.be.eql(opts); savedOptions.create.should.be.eql(opts);
done(err); done(err);
}); });
}); });
it('should receive options from the update method', function(done) { it('should receive options from the update method', function(done) {
var opts = { transaction: 'tx4' }; var opts = {transaction: 'tx4'};
Post.update({ title: 't1' }, { content: 'c1 --> c2' }, Post.update({title: 't1'}, {content: 'c1 --> c2'},
opts, function(err, p) { opts, function(err, p) {
savedOptions.update.should.be.eql(opts); savedOptions.update.should.be.eql(opts);
done(err); done(err);
@ -981,7 +982,7 @@ describe('Memory connector with observers', function() {
var events = []; var events = [];
ds.connector.execute = function(command, params, options, cb) { ds.connector.execute = function(command, params, options, cb) {
var self = this; var self = this;
var context = { command: command, params: params, options: options }; var context = {command: command, params: params, options: options};
self.notifyObserversOf('before execute', context, function(err) { self.notifyObserversOf('before execute', context, function(err) {
process.nextTick(function() { process.nextTick(function() {
if (err) return cb(err); if (err) return cb(err);
@ -1003,7 +1004,7 @@ describe('Memory connector with observers', function() {
next(); next();
}); });
ds.connector.execute('test', [1, 2], { x: 2 }, function(err) { ds.connector.execute('test', [1, 2], {x: 2}, function(err) {
if (err) return done(err); if (err) return done(err);
events.should.eql(['before execute', 'execute', 'after execute']); events.should.eql(['before execute', 'execute', 'after execute']);
done(); done();

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var jdb = require('../'); var jdb = require('../');
@ -16,8 +17,8 @@ var mixins = modelBuilder.mixins;
function timestamps(Model, options) { function timestamps(Model, options) {
Model.defineProperty('createdAt', { type: Date }); Model.defineProperty('createdAt', {type: Date});
Model.defineProperty('updatedAt', { type: Date }); Model.defineProperty('updatedAt', {type: Date});
var originalBeforeSave = Model.beforeSave; var originalBeforeSave = Model.beforeSave;
Model.beforeSave = function(next, data) { Model.beforeSave = function(next, data) {
@ -64,45 +65,45 @@ describe('Model class', function() {
it('should apply a mixin class', function() { it('should apply a mixin class', function() {
var Address = modelBuilder.define('Address', { var Address = modelBuilder.define('Address', {
street: { type: 'string', required: true }, street: {type: 'string', required: true},
city: { type: 'string', required: true }, city: {type: 'string', required: true},
}); });
var memory = new DataSource('mem', { connector: Memory }, modelBuilder); var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
var Item = memory.createModel('Item', { name: 'string' }, { var Item = memory.createModel('Item', {name: 'string'}, {
mixins: { Address: true }, mixins: {Address: true},
}); });
var properties = Item.definition.properties; var properties = Item.definition.properties;
properties.street.should.eql({ type: String, required: true }); properties.street.should.eql({type: String, required: true});
properties.city.should.eql({ type: String, required: true }); properties.city.should.eql({type: String, required: true});
}); });
it('should fail to apply an undefined mixin class', function() { it('should fail to apply an undefined mixin class', function() {
var memory = new DataSource('mem', { connector: Memory }, modelBuilder); var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
function applyMixin() { function applyMixin() {
memory.createModel('Item', { name: 'string' }, { memory.createModel('Item', {name: 'string'}, {
mixins: { UndefinedMixin: true }, mixins: {UndefinedMixin: true},
}); });
} }
should.throws(applyMixin, 'failed to apply undefined mixin class'); should.throws(applyMixin, 'failed to apply undefined mixin class');
}); });
it('should apply mixins', function(done) { it('should apply mixins', function(done) {
var memory = new DataSource('mem', { connector: Memory }, modelBuilder); var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
var Item = memory.createModel('Item', { name: 'string' }, { var Item = memory.createModel('Item', {name: 'string'}, {
mixins: { mixins: {
TimeStamp: true, TimeStamp: true,
Demo: { value: true }, Demo: {value: true},
Multi: [ Multi: [
{ key: 'foo', value: 'bar' }, {key: 'foo', value: 'bar'},
{ key: 'fox', value: 'baz' }, {key: 'fox', value: 'baz'},
], ],
}, },
}); });
Item.mixin('Example', { foo: 'bar' }); Item.mixin('Example', {foo: 'bar'});
Item.demoMixin.should.be.true; Item.demoMixin.should.be.true;
@ -110,23 +111,23 @@ describe('Model class', function() {
Item.multiMixin.fox.should.equal('baz'); Item.multiMixin.fox.should.equal('baz');
var properties = Item.definition.properties; var properties = Item.definition.properties;
properties.createdAt.should.eql({ type: Date }); properties.createdAt.should.eql({type: Date});
properties.updatedAt.should.eql({ type: Date }); properties.updatedAt.should.eql({type: Date});
Item.create({ name: 'Item 1' }, function(err, inst) { Item.create({name: 'Item 1'}, function(err, inst) {
inst.createdAt.should.be.a.date; inst.createdAt.should.be.a.date;
inst.updatedAt.should.be.a.date; inst.updatedAt.should.be.a.date;
inst.example().should.eql({ foo: 'bar' }); inst.example().should.eql({foo: 'bar'});
done(); done();
}); });
}); });
it('should fail to apply undefined mixin', function() { it('should fail to apply undefined mixin', function() {
var memory = new DataSource('mem', { connector: Memory }, modelBuilder); var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
var Item = memory.createModel('Item', { name: 'string' }); var Item = memory.createModel('Item', {name: 'string'});
function applyMixin() { function applyMixin() {
Item.mixin('UndefinedMixin', { foo: 'bar' }); Item.mixin('UndefinedMixin', {foo: 'bar'});
} }
should.throws(applyMixin, 'failed to apply undefined mixin'); should.throws(applyMixin, 'failed to apply undefined mixin');
}); });
@ -137,12 +138,12 @@ describe('Model class', function() {
beforeEach(function() { beforeEach(function() {
Address = modelBuilder.define('Address', { Address = modelBuilder.define('Address', {
street: { type: 'string', required: true }, street: {type: 'string', required: true},
city: { type: 'string', required: true }, city: {type: 'string', required: true},
}); });
var memory = new DataSource('mem', { connector: Memory }, modelBuilder); var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
Person = memory.createModel('Person', { name: 'string' }); Person = memory.createModel('Person', {name: 'string'});
Author = memory.createModel('Author', { name: 'string' }); Author = memory.createModel('Author', {name: 'string'});
}); });
it('should register mixin class into _mixins', function() { it('should register mixin class into _mixins', function() {

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
module.exports = { module.exports = {
// connector which uses custom field settings // connector which uses custom field settings
@ -19,7 +20,7 @@ module.exports = {
required: false, required: false,
// custom properties listed under a key matching the connector name // custom properties listed under a key matching the connector name
custom: { storage: 'quantum' }, custom: {storage: 'quantum'},
}, },
]); ]);
}, },

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var assert = require('assert'); var assert = require('assert');
@ -17,7 +18,7 @@ var ModelDefinition = require('../lib/model-definition');
describe('ModelDefinition class', function() { describe('ModelDefinition class', function() {
var memory; var memory;
beforeEach(function() { beforeEach(function() {
memory = new DataSource({ connector: Memory }); memory = new DataSource({connector: Memory});
}); });
it('should be able to define plain models', function(done) { it('should be able to define plain models', function(done) {
@ -67,7 +68,7 @@ describe('ModelDefinition class', function() {
var json = User.toJSON(); var json = User.toJSON();
User.defineProperty('id', { type: 'number', id: true }); User.defineProperty('id', {type: 'number', id: true});
assert.equal(User.properties.name.type, String); assert.equal(User.properties.name.type, String);
assert.equal(User.properties.bio.type, ModelBuilder.Text); assert.equal(User.properties.bio.type, ModelBuilder.Text);
assert.equal(User.properties.approved.type, Boolean); assert.equal(User.properties.approved.type, Boolean);
@ -77,7 +78,7 @@ describe('ModelDefinition class', function() {
assert.equal(User.properties.id.type, Number); assert.equal(User.properties.id.type, Number);
json = User.toJSON(); json = User.toJSON();
assert.deepEqual(json.properties.id, { type: 'Number', id: true }); assert.deepEqual(json.properties.id, {type: 'Number', id: true});
done(); done();
@ -116,10 +117,10 @@ describe('ModelDefinition class', function() {
assert.equal(json.properties.joinedAt.type, 'Date'); assert.equal(json.properties.joinedAt.type, 'Date');
assert.equal(json.properties.age.type, 'Number'); assert.equal(json.properties.age.type, 'Number');
assert.deepEqual(json.properties.address.type, { street: { type: 'String' }, assert.deepEqual(json.properties.address.type, {street: {type: 'String'},
city: { type: 'String' }, city: {type: 'String'},
zipCode: { type: 'String' }, zipCode: {type: 'String'},
state: { type: 'String' }}); state: {type: 'String'}});
done(); done();
@ -211,7 +212,7 @@ describe('ModelDefinition class', function() {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = new ModelDefinition(modelBuilder, 'User', { var User = new ModelDefinition(modelBuilder, 'User', {
userId: { type: String, id: true }, userId: {type: String, id: true},
name: 'string', name: 'string',
bio: ModelBuilder.Text, bio: ModelBuilder.Text,
approved: Boolean, approved: Boolean,
@ -228,8 +229,8 @@ describe('ModelDefinition class', function() {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = new ModelDefinition(modelBuilder, 'User', { var User = new ModelDefinition(modelBuilder, 'User', {
userId: { type: String, id: 2 }, userId: {type: String, id: 2},
userType: { type: String, id: 1 }, userType: {type: String, id: 1},
name: 'string', name: 'string',
bio: ModelBuilder.Text, bio: ModelBuilder.Text,
approved: Boolean, approved: Boolean,
@ -250,9 +251,9 @@ describe('ModelDefinition class', function() {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
var User = new ModelDefinition(modelBuilder, 'User', { var User = new ModelDefinition(modelBuilder, 'User', {
userId: { type: String, id: true, oracle: { column: 'ID' }}, userId: {type: String, id: true, oracle: {column: 'ID'}},
name: 'string', name: 'string',
}, { oracle: { table: 'USER' }}); }, {oracle: {table: 'USER'}});
assert.equal(User.tableName('oracle'), 'USER'); assert.equal(User.tableName('oracle'), 'USER');
assert.equal(User.tableName('mysql'), 'User'); assert.equal(User.tableName('mysql'), 'User');
@ -283,7 +284,7 @@ describe('ModelDefinition class', function() {
it('should ignore inherited options.base', function() { it('should ignore inherited options.base', function() {
var modelBuilder = memory.modelBuilder; var modelBuilder = memory.modelBuilder;
var base = modelBuilder.define('base'); var base = modelBuilder.define('base');
var child = base.extend('child', {}, { base: 'base' }); var child = base.extend('child', {}, {base: 'base'});
var grandChild = child.extend('grand-child'); var grandChild = child.extend('grand-child');
assert.equal('child', grandChild.base.modelName); assert.equal('child', grandChild.base.modelName);
assert(grandChild.prototype instanceof child); assert(grandChild.prototype instanceof child);
@ -292,7 +293,7 @@ describe('ModelDefinition class', function() {
it('should ignore inherited options.super', function() { it('should ignore inherited options.super', function() {
var modelBuilder = memory.modelBuilder; var modelBuilder = memory.modelBuilder;
var base = modelBuilder.define('base'); var base = modelBuilder.define('base');
var child = base.extend('child', {}, { super: 'base' }); var child = base.extend('child', {}, {super: 'base'});
var grandChild = child.extend('grand-child'); var grandChild = child.extend('grand-child');
assert.equal('child', grandChild.base.modelName); assert.equal('child', grandChild.base.modelName);
assert(grandChild.prototype instanceof child); assert(grandChild.prototype instanceof child);
@ -315,7 +316,7 @@ describe('ModelDefinition class', function() {
it('should not serialize protected properties of nested models into JSON', function(done) { it('should not serialize protected properties of nested models into JSON', function(done) {
var modelBuilder = memory.modelBuilder; var modelBuilder = memory.modelBuilder;
var Parent = memory.createModel('parent'); var Parent = memory.createModel('parent');
var Child = memory.createModel('child', {}, { protected: ['protectedProperty'] }); var Child = memory.createModel('child', {}, {protected: ['protectedProperty']});
Parent.hasMany(Child); Parent.hasMany(Child);
Parent.create({ Parent.create({
name: 'parent', name: 'parent',
@ -324,7 +325,7 @@ describe('ModelDefinition class', function() {
name: 'child', name: 'child',
protectedProperty: 'protectedValue', protectedProperty: 'protectedValue',
}, function(err, child) { }, function(err, child) {
Parent.find({ include: 'children' }, function(err, parents) { Parent.find({include: 'children'}, function(err, parents) {
var serialized = parents[0].toJSON(); var serialized = parents[0].toJSON();
var child = serialized.children[0]; var child = serialized.children[0];
assert.equal(child.name, 'child'); assert.equal(child.name, 'child');
@ -355,7 +356,7 @@ describe('ModelDefinition class', function() {
it('should not serialize hidden properties of nested models into JSON', function(done) { it('should not serialize hidden properties of nested models into JSON', function(done) {
var modelBuilder = memory.modelBuilder; var modelBuilder = memory.modelBuilder;
var Parent = memory.createModel('parent'); var Parent = memory.createModel('parent');
var Child = memory.createModel('child', {}, { hidden: ['secret'] }); var Child = memory.createModel('child', {}, {hidden: ['secret']});
Parent.hasMany(Child); Parent.hasMany(Child);
Parent.create({ Parent.create({
name: 'parent', name: 'parent',
@ -364,7 +365,7 @@ describe('ModelDefinition class', function() {
name: 'child', name: 'child',
secret: 'secret', secret: 'secret',
}, function(err, child) { }, function(err, child) {
Parent.find({ include: 'children' }, function(err, parents) { Parent.find({include: 'children'}, function(err, parents) {
var serialized = parents[0].toJSON(); var serialized = parents[0].toJSON();
var child = serialized.children[0]; var child = serialized.children[0];
assert.equal(child.name, 'child'); assert.equal(child.name, 'child');
@ -376,7 +377,7 @@ describe('ModelDefinition class', function() {
}); });
it('should throw error for property names containing dot', function() { it('should throw error for property names containing dot', function() {
(function() { memory.createModel('Dotted', { 'dot.name': String }); }) (function() { memory.createModel('Dotted', {'dot.name': String}); })
.should .should
.throw(/dot\(s\).*Dotted.*dot\.name/); .throw(/dot\(s\).*Dotted.*dot\.name/);
}); });
@ -385,7 +386,7 @@ describe('ModelDefinition class', function() {
var message = 'deprecation not reported'; var message = 'deprecation not reported';
process.once('deprecation', function(err) { message = err.message; }); process.once('deprecation', function(err) { message = err.message; });
memory.createModel('Ctor', { 'constructor': String }); memory.createModel('Ctor', {'constructor': String});
message.should.match(/Property name should not be "constructor" in Model: Ctor/); message.should.match(/Property name should not be "constructor" in Model: Ctor/);
}); });
@ -393,7 +394,7 @@ describe('ModelDefinition class', function() {
it('should throw error for dynamic property names containing dot', it('should throw error for dynamic property names containing dot',
function(done) { function(done) {
var Model = memory.createModel('DynamicDotted'); var Model = memory.createModel('DynamicDotted');
Model.create({ 'dot.name': 'dot.value' }, function(err) { Model.create({'dot.name': 'dot.value'}, function(err) {
err.should.be.instanceOf(Error); err.should.be.instanceOf(Error);
err.message.should.match(/dot\(s\).*DynamicDotted.*dot\.name/); err.message.should.match(/dot\(s\).*DynamicDotted.*dot\.name/);
done(); done();
@ -402,7 +403,7 @@ describe('ModelDefinition class', function() {
it('should throw error for dynamic property named constructor', function(done) { it('should throw error for dynamic property named constructor', function(done) {
var Model = memory.createModel('DynamicCtor'); var Model = memory.createModel('DynamicCtor');
Model.create({ 'constructor': 'myCtor' }, function(err) { Model.create({'constructor': 'myCtor'}, function(err) {
assert.equal(err.message, 'Property name "constructor" is not allowed in DynamicCtor data'); assert.equal(err.message, 'Property name "constructor" is not allowed in DynamicCtor data');
done(); done();
}); });

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var ValidationError = require('../..').ValidationError; var ValidationError = require('../..').ValidationError;
var contextTestHelpers = require('../helpers/context-test-helpers'); var contextTestHelpers = require('../helpers/context-test-helpers');
@ -18,7 +20,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupHelpers() { beforeEach(function setupHelpers() {
ctxRecorder = new ContextRecorder('hook not called'); ctxRecorder = new ContextRecorder('hook not called');
hookMonitor = new HookMonitor({ includeModelName: true }); hookMonitor = new HookMonitor({includeModelName: true});
expectedError = new Error('test error'); expectedError = new Error('test error');
}); });
@ -28,9 +30,9 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupDatabase() { beforeEach(function setupDatabase() {
Embedded = dataSource.createModel('Embedded', { Embedded = dataSource.createModel('Embedded', {
// Set id.generated to false to honor client side values // Set id.generated to false to honor client side values
id: { type: String, id: true, generated: false, default: uid.next }, id: {type: String, id: true, generated: false, default: uid.next},
name: { type: String, required: true }, name: {type: String, required: true},
extra: { type: String, required: false }, extra: {type: String, required: false},
}); });
Owner = dataSource.createModel('Owner', {}); Owner = dataSource.createModel('Owner', {});
@ -55,7 +57,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
function callCreate() { function callCreate() {
var item = new Embedded({ name: 'created' }); var item = new Embedded({name: 'created'});
return ownerInstance.embeddedList.create(item); return ownerInstance.embeddedList.create(item);
} }
@ -111,7 +113,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
// and produces a single "invalid" error only // and produces a single "invalid" error only
// Compare this to `embedsOne.create`, which correctly reports // Compare this to `embedsOne.create`, which correctly reports
// codes: { name: ['presence'] } // codes: { name: ['presence'] }
(err.details.codes || {}).should.eql({ embeddeds: ['invalid'] }); (err.details.codes || {}).should.eql({embeddeds: ['invalid']});
}); });
}); });

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var Promise = require('bluebird'); var Promise = require('bluebird');
var ValidationError = require('../..').ValidationError; var ValidationError = require('../..').ValidationError;
@ -18,7 +20,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
var ctxRecorder, hookMonitor, expectedError; var ctxRecorder, hookMonitor, expectedError;
beforeEach(function sharedSetup() { beforeEach(function sharedSetup() {
ctxRecorder = new ContextRecorder('hook not called'); ctxRecorder = new ContextRecorder('hook not called');
hookMonitor = new HookMonitor({ includeModelName: true }); hookMonitor = new HookMonitor({includeModelName: true});
expectedError = new Error('test error'); expectedError = new Error('test error');
}); });
@ -27,9 +29,9 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupDatabase() { beforeEach(function setupDatabase() {
Embedded = dataSource.createModel('Embedded', { Embedded = dataSource.createModel('Embedded', {
// Set id.generated to false to honor client side values // Set id.generated to false to honor client side values
id: { type: String, id: true, generated: false, default: uid.next }, id: {type: String, id: true, generated: false, default: uid.next},
name: { type: String, required: true }, name: {type: String, required: true},
extra: { type: String, required: false }, extra: {type: String, required: false},
}); });
Owner = dataSource.createModel('Owner', {}); Owner = dataSource.createModel('Owner', {});
@ -46,14 +48,14 @@ module.exports = function(dataSource, should, connectorCapabilities) {
} }
}); });
var ownerInstance, existingInstance; var ownerInstance, existingInstance, existingItem, existingItem;
beforeEach(function setupData() { beforeEach(function setupData() {
return Owner.create({}) return Owner.create({})
.then(function(inst) { .then(function(inst) {
ownerInstance = inst; ownerInstance = inst;
}) })
.then(function() { .then(function() {
var item = new Embedded({ name: 'created' }); var item = new Embedded({name: 'created'});
return ownerInstance.embeddedList.create(item).then(function(it) { return ownerInstance.embeddedList.create(item).then(function(it) {
existingItem = it; existingItem = it;
}); });

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var Promise = require('bluebird'); var Promise = require('bluebird');
var ValidationError = require('../..').ValidationError; var ValidationError = require('../..').ValidationError;
@ -18,7 +20,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
var ctxRecorder, hookMonitor, expectedError; var ctxRecorder, hookMonitor, expectedError;
beforeEach(function setupHelpers() { beforeEach(function setupHelpers() {
ctxRecorder = new ContextRecorder('hook not called'); ctxRecorder = new ContextRecorder('hook not called');
hookMonitor = new HookMonitor({ includeModelName: true }); hookMonitor = new HookMonitor({includeModelName: true});
expectedError = new Error('test error'); expectedError = new Error('test error');
}); });
@ -27,9 +29,9 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupDatabase() { beforeEach(function setupDatabase() {
Embedded = dataSource.createModel('Embedded', { Embedded = dataSource.createModel('Embedded', {
// Set id.generated to false to honor client side values // Set id.generated to false to honor client side values
id: { type: String, id: true, generated: false, default: uid.next }, id: {type: String, id: true, generated: false, default: uid.next},
name: { type: String, required: true }, name: {type: String, required: true},
extra: { type: String, required: false }, extra: {type: String, required: false},
}); });
Owner = dataSource.createModel('Owner', {}); Owner = dataSource.createModel('Owner', {});
@ -53,7 +55,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
ownerInstance = inst; ownerInstance = inst;
}) })
.then(function() { .then(function() {
var item = new Embedded({ name: 'created' }); var item = new Embedded({name: 'created'});
return ownerInstance.embeddedList.create(item).then(function(it) { return ownerInstance.embeddedList.create(item).then(function(it) {
existingItem = it; existingItem = it;
}); });
@ -68,7 +70,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
ownerInstance.embeddedList.updateById( ownerInstance.embeddedList.updateById(
existingItem.id, existingItem.id,
{ name: 'updated' }, {name: 'updated'},
function(err, result) { function(err, result) {
if (err) reject(err); if (err) reject(err);
else resolve(result); else resolve(result);
@ -125,7 +127,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
Embedded.observe('before save', invalidateEmbeddedModel); Embedded.observe('before save', invalidateEmbeddedModel);
return callUpdate().then(throwShouldHaveFailed, function(err) { return callUpdate().then(throwShouldHaveFailed, function(err) {
err.should.be.instanceOf(ValidationError); err.should.be.instanceOf(ValidationError);
(err.details.codes || {}).should.eql({ name: ['presence'] }); (err.details.codes || {}).should.eql({name: ['presence']});
}); });
}); });

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var ValidationError = require('../..').ValidationError; var ValidationError = require('../..').ValidationError;
var contextTestHelpers = require('../helpers/context-test-helpers'); var contextTestHelpers = require('../helpers/context-test-helpers');
@ -18,7 +20,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupHelpers() { beforeEach(function setupHelpers() {
ctxRecorder = new ContextRecorder('hook not called'); ctxRecorder = new ContextRecorder('hook not called');
hookMonitor = new HookMonitor({ includeModelName: true }); hookMonitor = new HookMonitor({includeModelName: true});
expectedError = new Error('test error'); expectedError = new Error('test error');
}); });
@ -28,9 +30,9 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupDatabase() { beforeEach(function setupDatabase() {
Embedded = dataSource.createModel('Embedded', { Embedded = dataSource.createModel('Embedded', {
// Set id.generated to false to honor client side values // Set id.generated to false to honor client side values
id: { type: String, id: true, generated: false, default: uid.next }, id: {type: String, id: true, generated: false, default: uid.next},
name: { type: String, required: true }, name: {type: String, required: true},
extra: { type: String, required: false }, extra: {type: String, required: false},
}); });
Owner = dataSource.createModel('Owner', {}); Owner = dataSource.createModel('Owner', {});
@ -55,7 +57,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
function callCreate() { function callCreate() {
var item = new Embedded({ name: 'created' }); var item = new Embedded({name: 'created'});
return ownerInstance.embeddedItem.create(item); return ownerInstance.embeddedItem.create(item);
} }
@ -106,7 +108,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
Embedded.observe('before save', invalidateEmbeddedModel); Embedded.observe('before save', invalidateEmbeddedModel);
return callCreate().then(throwShouldHaveFailed, function(err) { return callCreate().then(throwShouldHaveFailed, function(err) {
err.should.be.instanceOf(ValidationError); err.should.be.instanceOf(ValidationError);
(err.details.codes || {}).should.eql({ name: ['presence'] }); (err.details.codes || {}).should.eql({name: ['presence']});
}); });
}); });

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var ValidationError = require('../..').ValidationError; var ValidationError = require('../..').ValidationError;
var contextTestHelpers = require('../helpers/context-test-helpers'); var contextTestHelpers = require('../helpers/context-test-helpers');
@ -17,7 +19,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
var ctxRecorder, hookMonitor, expectedError; var ctxRecorder, hookMonitor, expectedError;
beforeEach(function sharedSetup() { beforeEach(function sharedSetup() {
ctxRecorder = new ContextRecorder('hook not called'); ctxRecorder = new ContextRecorder('hook not called');
hookMonitor = new HookMonitor({ includeModelName: true }); hookMonitor = new HookMonitor({includeModelName: true});
expectedError = new Error('test error'); expectedError = new Error('test error');
}); });
@ -26,9 +28,9 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupDatabase() { beforeEach(function setupDatabase() {
Embedded = dataSource.createModel('Embedded', { Embedded = dataSource.createModel('Embedded', {
// Set id.generated to false to honor client side values // Set id.generated to false to honor client side values
id: { type: String, id: true, generated: false, default: uid.next }, id: {type: String, id: true, generated: false, default: uid.next},
name: { type: String, required: true }, name: {type: String, required: true},
extra: { type: String, required: false }, extra: {type: String, required: false},
}); });
Owner = dataSource.createModel('Owner', {}); Owner = dataSource.createModel('Owner', {});
@ -45,14 +47,14 @@ module.exports = function(dataSource, should, connectorCapabilities) {
} }
}); });
var ownerInstance, existingInstance; var ownerInstance, existingInstance, existingItem;
beforeEach(function setupData() { beforeEach(function setupData() {
return Owner.create({}) return Owner.create({})
.then(function(inst) { .then(function(inst) {
ownerInstance = inst; ownerInstance = inst;
}) })
.then(function() { .then(function() {
var item = new Embedded({ name: 'created' }); var item = new Embedded({name: 'created'});
return ownerInstance.embeddedItem.create(item).then(function(it) { return ownerInstance.embeddedItem.create(item).then(function(it) {
existingItem = it; existingItem = it;
}); });

View File

@ -3,6 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var ValidationError = require('../..').ValidationError; var ValidationError = require('../..').ValidationError;
var contextTestHelpers = require('../helpers/context-test-helpers'); var contextTestHelpers = require('../helpers/context-test-helpers');
@ -17,7 +19,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
var ctxRecorder, hookMonitor, expectedError; var ctxRecorder, hookMonitor, expectedError;
beforeEach(function setupHelpers() { beforeEach(function setupHelpers() {
ctxRecorder = new ContextRecorder('hook not called'); ctxRecorder = new ContextRecorder('hook not called');
hookMonitor = new HookMonitor({ includeModelName: true }); hookMonitor = new HookMonitor({includeModelName: true});
expectedError = new Error('test error'); expectedError = new Error('test error');
}); });
@ -26,9 +28,9 @@ module.exports = function(dataSource, should, connectorCapabilities) {
beforeEach(function setupDatabase() { beforeEach(function setupDatabase() {
Embedded = dataSource.createModel('Embedded', { Embedded = dataSource.createModel('Embedded', {
// Set id.generated to false to honor client side values // Set id.generated to false to honor client side values
id: { type: String, id: true, generated: false, default: uid.next }, id: {type: String, id: true, generated: false, default: uid.next},
name: { type: String, required: true }, name: {type: String, required: true},
extra: { type: String, required: false }, extra: {type: String, required: false},
}); });
Owner = dataSource.createModel('Owner', {}); Owner = dataSource.createModel('Owner', {});
@ -52,7 +54,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
ownerInstance = inst; ownerInstance = inst;
}) })
.then(function() { .then(function() {
var item = new Embedded({ name: 'created' }); var item = new Embedded({name: 'created'});
return ownerInstance.embeddedItem.create(item).then(function(it) { return ownerInstance.embeddedItem.create(item).then(function(it) {
existingItem = it; existingItem = it;
}); });
@ -63,7 +65,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
function callUpdate() { function callUpdate() {
return ownerInstance.embeddedItem.update({ name: 'updated' }); return ownerInstance.embeddedItem.update({name: 'updated'});
} }
it('triggers hooks in the correct order', function() { it('triggers hooks in the correct order', function() {
@ -115,7 +117,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
Embedded.observe('before save', invalidateEmbeddedModel); Embedded.observe('before save', invalidateEmbeddedModel);
return callUpdate().then(throwShouldHaveFailed, function(err) { return callUpdate().then(throwShouldHaveFailed, function(err) {
err.should.be.instanceOf(ValidationError); err.should.be.instanceOf(ValidationError);
(err.details.codes || {}).should.eql({ name: ['presence'] }); (err.details.codes || {}).should.eql({name: ['presence']});
}); });
}); });

View File

@ -1,3 +1,5 @@
'use strict';
var debug = require('debug')('test'); var debug = require('debug')('test');
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var async = require('async'); var async = require('async');
var should = require('./init.js'); var should = require('./init.js');
var db, User, options, ModelWithForceId, whereCount = 0; var db, User, options, ModelWithForceId, whereCount = 0;
@ -12,8 +13,8 @@ var ValidationError = j.ValidationError;
var INITIAL_NAME = 'Bert'; var INITIAL_NAME = 'Bert';
var NEW_NAME = 'Ernie'; var NEW_NAME = 'Ernie';
var INVALID_DATA = { name: null }; var INVALID_DATA = {name: null};
var VALID_DATA = { name: INITIAL_NAME }; var VALID_DATA = {name: INITIAL_NAME};
describe('optional-validation', function() { describe('optional-validation', function() {
@ -21,17 +22,17 @@ describe('optional-validation', function() {
db = getSchema(); db = getSchema();
ModelWithForceId = db.createModel( ModelWithForceId = db.createModel(
'ModelWithForceId', 'ModelWithForceId',
{ name: String }, {name: String},
{ forceId: true }); {forceId: true});
User = db.define('User', { User = db.define('User', {
seq: { type: Number, index: true }, seq: {type: Number, index: true},
name: { type: String, index: true, sort: true }, name: {type: String, index: true, sort: true},
email: { type: String, index: true }, email: {type: String, index: true},
birthday: { type: Date, index: true }, birthday: {type: Date, index: true},
role: { type: String, index: true }, role: {type: String, index: true},
order: { type: Number, index: true, sort: true }, order: {type: Number, index: true, sort: true},
vip: { type: Boolean }, vip: {type: Boolean},
}, { forceId: true, strict: true }); }, {forceId: true, strict: true});
db.automigrate(['ModelWithForceId', 'User'], done); db.automigrate(['ModelWithForceId', 'User'], done);
}); });
@ -55,7 +56,7 @@ describe('optional-validation', function() {
function expectCreateSuccess(data, done) { function expectCreateSuccess(data, done) {
if (done === undefined && typeof data === 'function') { if (done === undefined && typeof data === 'function') {
done = data; done = data;
data = { name: INITIAL_NAME }; data = {name: INITIAL_NAME};
} }
return function(err, instance) { return function(err, instance) {
if (err) return done(err); if (err) return done(err);
@ -72,7 +73,7 @@ describe('optional-validation', function() {
function expectChangeSuccess(data, done) { function expectChangeSuccess(data, done) {
if (done === undefined && typeof data === 'function') { if (done === undefined && typeof data === 'function') {
done = data; done = data;
data = { name: NEW_NAME }; data = {name: NEW_NAME};
} }
return function(err, instance) { return function(err, instance) {
if (err) return done(err); if (err) return done(err);
@ -87,36 +88,36 @@ describe('optional-validation', function() {
} }
function createUserAndChangeName(name, cb) { function createUserAndChangeName(name, cb) {
User.create(VALID_DATA, { validate: true }, function(err, d) { User.create(VALID_DATA, {validate: true}, function(err, d) {
d.name = name; d.name = name;
cb(err, d); cb(err, d);
}); });
} }
function createUser(cb) { function createUser(cb) {
User.create(VALID_DATA, { validate: true }, cb); User.create(VALID_DATA, {validate: true}, cb);
} }
function callUpdateOrCreateWithExistingUserId(name, options, cb) { function callUpdateOrCreateWithExistingUserId(name, options, cb) {
User.create({ 'name': 'Groover' }, function(err, user) { User.create({'name': 'Groover'}, function(err, user) {
if (err) return cb(err); if (err) return cb(err);
var data = { name: name }; var data = {name: name};
data.id = user.id; data.id = user.id;
User.updateOrCreate(data, options, cb); User.updateOrCreate(data, options, cb);
}); });
} }
function getNewWhere() { function getNewWhere() {
return { name: 'DoesNotExist' + (whereCount++) }; return {name: 'DoesNotExist' + (whereCount++)};
} }
describe('forceId', function() { describe('forceId', function() {
context('replaceAttributes', function() { context('replaceAttributes', function() {
it('should not fail if you do not pass the Primary key in data object', it('should not fail if you do not pass the Primary key in data object',
function(done) { function(done) {
ModelWithForceId.create({ name: 'foo' }, function(err, created) { ModelWithForceId.create({name: 'foo'}, function(err, created) {
if (err) return done(err); if (err) return done(err);
created.replaceAttributes({ name: 'bar' }, function(err, data) { created.replaceAttributes({name: 'bar'}, function(err, data) {
done(err); done(err);
}); });
}); });
@ -124,9 +125,9 @@ describe('optional-validation', function() {
it('should fail if you pass the Primary key in data object', it('should fail if you pass the Primary key in data object',
function(done) { function(done) {
ModelWithForceId.create({ name: 'foo' }, function(err, created) { ModelWithForceId.create({name: 'foo'}, function(err, created) {
if (err) return done(err); if (err) return done(err);
created.replaceAttributes({ name: 'bar', id: 999 }, created.replaceAttributes({name: 'bar', id: 999},
function(err, data) { function(err, data) {
should.exist(err); should.exist(err);
done(); done();
@ -140,19 +141,19 @@ describe('optional-validation', function() {
describe('method create', function() { describe('method create', function() {
it('should throw on create with validate:true with invalid data', function(done) { it('should throw on create with validate:true with invalid data', function(done) {
User.create(INVALID_DATA, { validate: true }, expectValidationError(done)); User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
}); });
it('should NOT throw on create with validate:false with invalid data', function(done) { it('should NOT throw on create with validate:false with invalid data', function(done) {
User.create(INVALID_DATA, { validate: false }, expectCreateSuccess(INVALID_DATA, done)); User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on create with validate:true with valid data', function(done) { it('should NOT throw on create with validate:true with valid data', function(done) {
User.create(VALID_DATA, { validate: true }, expectCreateSuccess(done)); User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
}); });
it('should NOT throw on create with validate:false with valid data', function(done) { it('should NOT throw on create with validate:false with valid data', function(done) {
User.create(VALID_DATA, { validate: false }, expectCreateSuccess(done)); User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
}); });
it('should throw on create with invalid data', function(done) { it('should throw on create with invalid data', function(done) {
@ -167,25 +168,25 @@ describe('optional-validation', function() {
describe('method findOrCreate', function() { describe('method findOrCreate', function() {
it('should throw on findOrCreate with validate:true with invalid data', it('should throw on findOrCreate with validate:true with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, { validate: true }, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on findOrCreate with validate:false with invalid data', it('should NOT throw on findOrCreate with validate:false with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, { validate: false }, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
expectCreateSuccess(INVALID_DATA, done)); expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on findOrCreate with validate:true with valid data', it('should NOT throw on findOrCreate with validate:true with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, { validate: true }, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should NOT throw on findOrCreate with validate:false with valid data', it('should NOT throw on findOrCreate with validate:false with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, { validate: false }, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
@ -201,25 +202,25 @@ describe('optional-validation', function() {
describe('method updateOrCreate on existing data', function() { describe('method updateOrCreate on existing data', function() {
it('should throw on updateOrCreate(id) with validate:true with invalid data', it('should throw on updateOrCreate(id) with validate:true with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, { validate: true }, callUpdateOrCreateWithExistingUserId(null, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data', it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, { validate: false }, callUpdateOrCreateWithExistingUserId(null, {validate: false},
expectChangeSuccess(INVALID_DATA, done)); expectChangeSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:true with valid data', it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, { validate: true }, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with valid data', it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, { validate: false }, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
@ -236,25 +237,25 @@ describe('optional-validation', function() {
describe('method save', function() { describe('method save', function() {
it('should throw on save with {validate:true} with invalid data', function(done) { it('should throw on save with {validate:true} with invalid data', function(done) {
createUserAndChangeName(null, function(err, d) { createUserAndChangeName(null, function(err, d) {
d.save({ validate: true }, expectValidationError(done)); d.save({validate: true}, expectValidationError(done));
}); });
}); });
it('should NOT throw on save with {validate:false} with invalid data', function(done) { it('should NOT throw on save with {validate:false} with invalid data', function(done) {
createUserAndChangeName(null, function(err, d) { createUserAndChangeName(null, function(err, d) {
d.save({ validate: false }, expectChangeSuccess(INVALID_DATA, done)); d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
}); });
}); });
it('should NOT throw on save with {validate:true} with valid data', function(done) { it('should NOT throw on save with {validate:true} with valid data', function(done) {
createUserAndChangeName(NEW_NAME, function(err, d) { createUserAndChangeName(NEW_NAME, function(err, d) {
d.save({ validate: true }, expectChangeSuccess(done)); d.save({validate: true}, expectChangeSuccess(done));
}); });
}); });
it('should NOT throw on save with {validate:false} with valid data', function(done) { it('should NOT throw on save with {validate:false} with valid data', function(done) {
createUserAndChangeName(NEW_NAME, function(err, d) { createUserAndChangeName(NEW_NAME, function(err, d) {
d.save({ validate: false }, expectChangeSuccess(done)); d.save({validate: false}, expectChangeSuccess(done));
}); });
}); });
@ -274,25 +275,25 @@ describe('optional-validation', function() {
describe('method updateAttributes', function() { describe('method updateAttributes', function() {
it('should throw on updateAttributes with {validate:true} with invalid data', function(done) { it('should throw on updateAttributes with {validate:true} with invalid data', function(done) {
createUser(function(err, d) { createUser(function(err, d) {
d.updateAttributes(INVALID_DATA, { validate: true }, expectValidationError(done)); d.updateAttributes(INVALID_DATA, {validate: true}, expectValidationError(done));
}); });
}); });
it('should NOT throw on updateAttributes with {validate:false} with invalid data', function(done) { it('should NOT throw on updateAttributes with {validate:false} with invalid data', function(done) {
createUser(function(err, d) { createUser(function(err, d) {
d.updateAttributes(INVALID_DATA, { validate: false }, expectChangeSuccess(INVALID_DATA, done)); d.updateAttributes(INVALID_DATA, {validate: false}, expectChangeSuccess(INVALID_DATA, done));
}); });
}); });
it('should NOT throw on updateAttributes with {validate:true} with valid data', function(done) { it('should NOT throw on updateAttributes with {validate:true} with valid data', function(done) {
createUser(function(err, d) { createUser(function(err, d) {
d.updateAttributes({ 'name': NEW_NAME }, { validate: true }, expectChangeSuccess(done)); d.updateAttributes({'name': NEW_NAME}, {validate: true}, expectChangeSuccess(done));
}); });
}); });
it('should NOT throw on updateAttributes with {validate:false} with valid data', function(done) { it('should NOT throw on updateAttributes with {validate:false} with valid data', function(done) {
createUser(function(err, d) { createUser(function(err, d) {
d.updateAttributes({ 'name': NEW_NAME }, { validate: false }, expectChangeSuccess(done)); d.updateAttributes({'name': NEW_NAME}, {validate: false}, expectChangeSuccess(done));
}); });
}); });
@ -304,7 +305,7 @@ describe('optional-validation', function() {
it('should NOT throw on updateAttributes(cb) with valid data', function(done) { it('should NOT throw on updateAttributes(cb) with valid data', function(done) {
createUser(function(err, d) { createUser(function(err, d) {
d.updateAttributes({ 'name': NEW_NAME }, expectChangeSuccess(done)); d.updateAttributes({'name': NEW_NAME}, expectChangeSuccess(done));
}); });
}); });
}); });
@ -320,19 +321,19 @@ describe('optional-validation', function() {
describe('method create', function() { describe('method create', function() {
it('should throw on create with validate:true with invalid data', function(done) { it('should throw on create with validate:true with invalid data', function(done) {
User.create(INVALID_DATA, { validate: true }, expectValidationError(done)); User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
}); });
it('should NOT throw on create with validate:false with invalid data', function(done) { it('should NOT throw on create with validate:false with invalid data', function(done) {
User.create(INVALID_DATA, { validate: false }, expectCreateSuccess(INVALID_DATA, done)); User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on create with validate:true with valid data', function(done) { it('should NOT throw on create with validate:true with valid data', function(done) {
User.create(VALID_DATA, { validate: true }, expectCreateSuccess(done)); User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
}); });
it('should NOT throw on create with validate:false with valid data', function(done) { it('should NOT throw on create with validate:false with valid data', function(done) {
User.create(VALID_DATA, { validate: false }, expectCreateSuccess(done)); User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
}); });
it('should NOT throw on create with invalid data', function(done) { it('should NOT throw on create with invalid data', function(done) {
@ -347,25 +348,25 @@ describe('optional-validation', function() {
describe('method findOrCreate', function() { describe('method findOrCreate', function() {
it('should throw on findOrCreate with validate:true with invalid data', it('should throw on findOrCreate with validate:true with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, { validate: true }, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on findOrCreate with validate:false with invalid data', it('should NOT throw on findOrCreate with validate:false with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, { validate: false }, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
expectCreateSuccess(INVALID_DATA, done)); expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on findOrCreate with validate:true with valid data', it('should NOT throw on findOrCreate with validate:true with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, { validate: true }, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should NOT throw on findOrCreate with validate:false with valid data', it('should NOT throw on findOrCreate with validate:false with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, { validate: false }, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
@ -382,25 +383,25 @@ describe('optional-validation', function() {
describe('method updateOrCreate on existing data', function() { describe('method updateOrCreate on existing data', function() {
it('should throw on updateOrCreate(id) with validate:true with invalid data', it('should throw on updateOrCreate(id) with validate:true with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, { validate: true }, callUpdateOrCreateWithExistingUserId(null, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data', it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, { validate: false }, callUpdateOrCreateWithExistingUserId(null, {validate: false},
expectChangeSuccess(INVALID_DATA, done)); expectChangeSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:true with valid data', it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, { validate: true }, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with valid data', it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, { validate: false }, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
@ -416,25 +417,25 @@ describe('optional-validation', function() {
describe('method save', function() { describe('method save', function() {
it('should throw on save with {validate:true} with invalid data', function(done) { it('should throw on save with {validate:true} with invalid data', function(done) {
createUserAndChangeName(null, function(err, d) { createUserAndChangeName(null, function(err, d) {
d.save({ validate: true }, expectValidationError(done)); d.save({validate: true}, expectValidationError(done));
}); });
}); });
it('should NOT throw on save with {validate:false} with invalid data', function(done) { it('should NOT throw on save with {validate:false} with invalid data', function(done) {
createUserAndChangeName(null, function(err, d) { createUserAndChangeName(null, function(err, d) {
d.save({ validate: false }, expectChangeSuccess(INVALID_DATA, done)); d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
}); });
}); });
it('should NOT throw on save with {validate:true} with valid data', function(done) { it('should NOT throw on save with {validate:true} with valid data', function(done) {
createUserAndChangeName(NEW_NAME, function(err, d) { createUserAndChangeName(NEW_NAME, function(err, d) {
d.save({ validate: true }, expectChangeSuccess(done)); d.save({validate: true}, expectChangeSuccess(done));
}); });
}); });
it('should NOT throw on save with {validate:false} with valid data', function(done) { it('should NOT throw on save with {validate:false} with valid data', function(done) {
createUserAndChangeName(NEW_NAME, function(err, d) { createUserAndChangeName(NEW_NAME, function(err, d) {
d.save({ validate: false }, expectChangeSuccess(done)); d.save({validate: false}, expectChangeSuccess(done));
}); });
}); });
@ -462,19 +463,19 @@ describe('optional-validation', function() {
describe('method create', function() { describe('method create', function() {
it('should throw on create with validate:true with invalid data', function(done) { it('should throw on create with validate:true with invalid data', function(done) {
User.create(INVALID_DATA, { validate: true }, expectValidationError(done)); User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
}); });
it('should NOT throw on create with validate:false with invalid data', function(done) { it('should NOT throw on create with validate:false with invalid data', function(done) {
User.create(INVALID_DATA, { validate: false }, expectCreateSuccess(INVALID_DATA, done)); User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on create with validate:true with valid data', function(done) { it('should NOT throw on create with validate:true with valid data', function(done) {
User.create(VALID_DATA, { validate: true }, expectCreateSuccess(done)); User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
}); });
it('should NOT throw on create with validate:false with valid data', function(done) { it('should NOT throw on create with validate:false with valid data', function(done) {
User.create(VALID_DATA, { validate: false }, expectCreateSuccess(done)); User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
}); });
it('should throw on create with invalid data', function(done) { it('should throw on create with invalid data', function(done) {
@ -489,25 +490,25 @@ describe('optional-validation', function() {
describe('method findOrCreate', function() { describe('method findOrCreate', function() {
it('should throw on findOrCreate with validate:true with invalid data', it('should throw on findOrCreate with validate:true with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, { validate: true }, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on findOrCreate with validate:false with invalid data', it('should NOT throw on findOrCreate with validate:false with invalid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), INVALID_DATA, { validate: false }, User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
expectCreateSuccess(INVALID_DATA, done)); expectCreateSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on findOrCreate with validate:true with valid data', it('should NOT throw on findOrCreate with validate:true with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, { validate: true }, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
it('should NOT throw on findOrCreate with validate:false with valid data', it('should NOT throw on findOrCreate with validate:false with valid data',
function(done) { function(done) {
User.findOrCreate(getNewWhere(), VALID_DATA, { validate: false }, User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
expectCreateSuccess(done)); expectCreateSuccess(done));
}); });
@ -523,25 +524,25 @@ describe('optional-validation', function() {
describe('method updateOrCreate on existing data', function() { describe('method updateOrCreate on existing data', function() {
it('should throw on updateOrCreate(id) with validate:true with invalid data', it('should throw on updateOrCreate(id) with validate:true with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, { validate: true }, callUpdateOrCreateWithExistingUserId(null, {validate: true},
expectValidationError(done)); expectValidationError(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data', it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(null, { validate: false }, callUpdateOrCreateWithExistingUserId(null, {validate: false},
expectChangeSuccess(INVALID_DATA, done)); expectChangeSuccess(INVALID_DATA, done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:true with valid data', it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, { validate: true }, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
it('should NOT throw on updateOrCreate(id) with validate:false with valid data', it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
function(done) { function(done) {
callUpdateOrCreateWithExistingUserId(NEW_NAME, { validate: false }, callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
expectChangeSuccess(done)); expectChangeSuccess(done));
}); });
@ -563,19 +564,19 @@ describe('optional-validation', function() {
it('should NOT throw on save with {validate:false} with invalid data', function(done) { it('should NOT throw on save with {validate:false} with invalid data', function(done) {
createUserAndChangeName(null, function(err, d) { createUserAndChangeName(null, function(err, d) {
d.save({ validate: false }, expectChangeSuccess(INVALID_DATA, done)); d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
}); });
}); });
it('should NOT throw on save with {validate:true} with valid data', function(done) { it('should NOT throw on save with {validate:true} with valid data', function(done) {
createUserAndChangeName(NEW_NAME, function(err, d) { createUserAndChangeName(NEW_NAME, function(err, d) {
d.save({ validate: true }, expectChangeSuccess(done)); d.save({validate: true}, expectChangeSuccess(done));
}); });
}); });
it('should NOT throw on save with {validate:false} with valid data', function(done) { it('should NOT throw on save with {validate:false} with valid data', function(done) {
createUserAndChangeName(NEW_NAME, function(err, d) { createUserAndChangeName(NEW_NAME, function(err, d) {
d.save({ validate: false }, expectChangeSuccess(done)); d.save({validate: false}, expectChangeSuccess(done));
}); });
}); });

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var db = getSchema(), slave = getSchema(), Model, SlaveModel; var db = getSchema(), slave = getSchema(), Model, SlaveModel;

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var db, Railway, Station; var db, Railway, Station;
@ -13,7 +14,7 @@ describe('scope', function() {
before(function() { before(function() {
db = getSchema(); db = getSchema();
Railway = db.define('Railway', { Railway = db.define('Railway', {
URID: { type: String, index: true }, URID: {type: String, index: true},
}, { }, {
scopes: { scopes: {
highSpeed: { highSpeed: {
@ -24,11 +25,11 @@ describe('scope', function() {
}, },
}); });
Station = db.define('Station', { Station = db.define('Station', {
USID: { type: String, index: true }, USID: {type: String, index: true},
capacity: { type: Number, index: true }, capacity: {type: Number, index: true},
thoughput: { type: Number, index: true }, thoughput: {type: Number, index: true},
isActive: { type: Boolean, index: true }, isActive: {type: Boolean, index: true},
isUndeground: { type: Boolean, index: true }, isUndeground: {type: Boolean, index: true},
}); });
}); });
@ -44,7 +45,7 @@ describe('scope', function() {
}); });
it('should define scope with query', function(done) { it('should define scope with query', function(done) {
Station.scope('active', { where: { isActive: true }}); Station.scope('active', {where: {isActive: true}});
Station.scopes.should.have.property('active'); Station.scopes.should.have.property('active');
Station.active.create(function(err, station) { Station.active.create(function(err, station) {
should.not.exist(err); should.not.exist(err);
@ -56,8 +57,8 @@ describe('scope', function() {
}); });
it('should allow scope chaining', function(done) { it('should allow scope chaining', function(done) {
Station.scope('active', { where: { isActive: true }}); Station.scope('active', {where: {isActive: true}});
Station.scope('subway', { where: { isUndeground: true }}); Station.scope('subway', {where: {isUndeground: true}});
Station.active.subway.create(function(err, station) { Station.active.subway.create(function(err, station) {
should.not.exist(err); should.not.exist(err);
should.exist(station); should.exist(station);
@ -68,9 +69,9 @@ describe('scope', function() {
}); });
it('should query all', function(done) { it('should query all', function(done) {
Station.scope('active', { where: { isActive: true }}); Station.scope('active', {where: {isActive: true}});
Station.scope('inactive', { where: { isActive: false }}); Station.scope('inactive', {where: {isActive: false}});
Station.scope('ground', { where: { isUndeground: true }}); Station.scope('ground', {where: {isUndeground: true}});
Station.active.ground.create(function() { Station.active.ground.create(function() {
Station.inactive.ground.create(function() { Station.inactive.ground.create(function() {
Station.ground.inactive(function(err, ss) { Station.ground.inactive(function(err, ss) {
@ -82,7 +83,7 @@ describe('scope', function() {
}); });
it('should not cache any results', function(done) { it('should not cache any results', function(done) {
Station.scope('active', { where: { isActive: true }}); Station.scope('active', {where: {isActive: true}});
Station.active.create(function(err, s) { Station.active.create(function(err, s) {
if (err) return done(err); if (err) return done(err);
s.isActive.should.be.true; s.isActive.should.be.true;
@ -110,10 +111,10 @@ describe('scope - order', function() {
before(function() { before(function() {
db = getSchema(); db = getSchema();
Station = db.define('Station', { Station = db.define('Station', {
name: { type: String, index: true }, name: {type: String, index: true},
order: { type: Number, index: true }, order: {type: Number, index: true},
}); });
Station.scope('reverse', { order: 'order DESC' }); Station.scope('reverse', {order: 'order DESC'});
}); });
beforeEach(function(done) { beforeEach(function(done) {
@ -121,15 +122,15 @@ describe('scope - order', function() {
}); });
beforeEach(function(done) { beforeEach(function(done) {
Station.create({ name: 'a', order: 1 }, done); Station.create({name: 'a', order: 1}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Station.create({ name: 'b', order: 2 }, done); Station.create({name: 'b', order: 2}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Station.create({ name: 'c', order: 3 }, done); Station.create({name: 'c', order: 3}, done);
}); });
it('should define scope with default order', function(done) { it('should define scope with default order', function(done) {
@ -145,7 +146,7 @@ describe('scope - order', function() {
}); });
it('should override default scope order', function(done) { it('should override default scope order', function(done) {
Station.reverse({ order: 'order ASC' }, function(err, stations) { Station.reverse({order: 'order ASC'}, function(err, stations) {
stations[0].name.should.equal('a'); stations[0].name.should.equal('a');
stations[0].order.should.equal(1); stations[0].order.should.equal(1);
stations[1].name.should.equal('b'); stations[1].name.should.equal('b');
@ -165,15 +166,15 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
before(function() { before(function() {
db = getSchema(); db = getSchema();
Station = db.define('Station', { Station = db.define('Station', {
name: { type: String, index: true }, name: {type: String, index: true},
order: { type: Number, index: true }, order: {type: Number, index: true},
active: { type: Boolean, index: true, default: true }, active: {type: Boolean, index: true, default: true},
flagged: { type: Boolean, index: true, default: false }, flagged: {type: Boolean, index: true, default: false},
}); });
Station.scope('ordered', { order: 'order' }); Station.scope('ordered', {order: 'order'});
Station.scope('active', { where: { active: true }}); Station.scope('active', {where: {active: true}});
Station.scope('inactive', { where: { active: false }}); Station.scope('inactive', {where: {active: false}});
Station.scope('flagged', { where: { flagged: true }}); Station.scope('flagged', {where: {flagged: true}});
}); });
beforeEach(function(done) { beforeEach(function(done) {
@ -181,22 +182,22 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
}); });
beforeEach(function(done) { beforeEach(function(done) {
Station.create({ name: 'b', order: 2, active: false }, done); Station.create({name: 'b', order: 2, active: false}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Station.create({ name: 'a', order: 1 }, function(err, inst) { Station.create({name: 'a', order: 1}, function(err, inst) {
stationA = inst; stationA = inst;
done(); done();
}); });
}); });
beforeEach(function(done) { beforeEach(function(done) {
Station.create({ name: 'd', order: 4, active: false }, done); Station.create({name: 'd', order: 4, active: false}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Station.create({ name: 'c', order: 3 }, done); Station.create({name: 'c', order: 3}, done);
}); });
it('should find all - verify', function(done) { it('should find all - verify', function(done) {
@ -220,7 +221,7 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
}); });
it('should find one - with filter', function(done) { it('should find one - with filter', function(done) {
Station.active.findOne({ where: { name: 'c' }}, function(err, station) { Station.active.findOne({where: {name: 'c'}}, function(err, station) {
should.not.exist(err); should.not.exist(err);
station.name.should.equal('c'); station.name.should.equal('c');
done(); done();
@ -260,7 +261,7 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
}); });
it('should count filtered - active', function(done) { it('should count filtered - active', function(done) {
Station.active.count({ order: { gt: 1 }}, function(err, count) { Station.active.count({order: {gt: 1}}, function(err, count) {
should.not.exist(err); should.not.exist(err);
count.should.equal(1); count.should.equal(1);
done(); done();
@ -268,7 +269,7 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
}); });
it('should count filtered - inactive', function(done) { it('should count filtered - inactive', function(done) {
Station.inactive.count({ order: 2 }, function(err, count) { Station.inactive.count({order: 2}, function(err, count) {
should.not.exist(err); should.not.exist(err);
count.should.equal(1); count.should.equal(1);
done(); done();
@ -276,7 +277,7 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
}); });
it('should allow updateAll', function(done) { it('should allow updateAll', function(done) {
Station.inactive.updateAll({ flagged: true }, function(err, result) { Station.inactive.updateAll({flagged: true}, function(err, result) {
should.not.exist(err); should.not.exist(err);
result.count.should.equal(2); result.count.should.equal(2);
verify(); verify();
@ -292,7 +293,7 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
}); });
it('should allow filtered updateAll', function(done) { it('should allow filtered updateAll', function(done) {
Station.ordered.updateAll({ active: true }, { flagged: true }, function(err, result) { Station.ordered.updateAll({active: true}, {flagged: true}, function(err, result) {
should.not.exist(err); should.not.exist(err);
result.count.should.equal(2); result.count.should.equal(2);
verify(); verify();
@ -308,7 +309,7 @@ describe('scope - filtered count, updateAll and destroyAll', function() {
}); });
it('should allow filtered destroyAll', function(done) { it('should allow filtered destroyAll', function(done) {
Station.ordered.destroyAll({ active: false }, function(err) { Station.ordered.destroyAll({active: false}, function(err) {
should.not.exist(err); should.not.exist(err);
verify(); verify();
}); });
@ -333,15 +334,15 @@ describe('scope - dynamic target class', function() {
before(function() { before(function() {
db = getSchema(); db = getSchema();
Image = db.define('Image', { name: String }); Image = db.define('Image', {name: String});
Video = db.define('Video', { name: String }); Video = db.define('Video', {name: String});
Collection = db.define('Collection', { name: String, modelName: String }); Collection = db.define('Collection', {name: String, modelName: String});
Collection.scope('items', function() { Collection.scope('items', function() {
return {}; // could return a scope based on `this` (receiver) return {}; // could return a scope based on `this` (receiver)
}, null, {}, { isStatic: false, modelTo: function(receiver) { }, null, {}, {isStatic: false, modelTo: function(receiver) {
return db.models[receiver.modelName]; return db.models[receiver.modelName];
} }); }});
}); });
beforeEach(function(done) { beforeEach(function(done) {
@ -353,27 +354,27 @@ describe('scope - dynamic target class', function() {
}); });
beforeEach(function(done) { beforeEach(function(done) {
Collection.create({ name: 'Images', modelName: 'Image' }, done); Collection.create({name: 'Images', modelName: 'Image'}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Collection.create({ name: 'Videos', modelName: 'Video' }, done); Collection.create({name: 'Videos', modelName: 'Video'}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Collection.create({ name: 'Things', modelName: 'Unknown' }, done); Collection.create({name: 'Things', modelName: 'Unknown'}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Image.create({ name: 'Image A' }, done); Image.create({name: 'Image A'}, done);
}); });
beforeEach(function(done) { beforeEach(function(done) {
Video.create({ name: 'Video A' }, done); Video.create({name: 'Video A'}, done);
}); });
it('should deduce modelTo at runtime - Image', function(done) { it('should deduce modelTo at runtime - Image', function(done) {
Collection.findOne({ where: { modelName: 'Image' }}, function(err, coll) { Collection.findOne({where: {modelName: 'Image'}}, function(err, coll) {
should.not.exist(err); should.not.exist(err);
coll.name.should.equal('Images'); coll.name.should.equal('Images');
coll.items(function(err, items) { coll.items(function(err, items) {
@ -387,7 +388,7 @@ describe('scope - dynamic target class', function() {
}); });
it('should deduce modelTo at runtime - Video', function(done) { it('should deduce modelTo at runtime - Video', function(done) {
Collection.findOne({ where: { modelName: 'Video' }}, function(err, coll) { Collection.findOne({where: {modelName: 'Video'}}, function(err, coll) {
should.not.exist(err); should.not.exist(err);
coll.name.should.equal('Videos'); coll.name.should.equal('Videos');
coll.items(function(err, items) { coll.items(function(err, items) {
@ -401,7 +402,7 @@ describe('scope - dynamic target class', function() {
}); });
it('should throw if modelTo is invalid', function(done) { it('should throw if modelTo is invalid', function(done) {
Collection.findOne({ where: { name: 'Things' }}, function(err, coll) { Collection.findOne({where: {name: 'Things'}}, function(err, coll) {
should.not.exist(err); should.not.exist(err);
coll.modelName.should.equal('Unknown'); coll.modelName.should.equal('Unknown');
(function() { (function() {
@ -419,16 +420,16 @@ describe('scope - dynamic function', function() {
before(function() { before(function() {
db = getSchema(); db = getSchema();
Item = db.define('Item', { title: Number, creator: Number }); Item = db.define('Item', {title: Number, creator: Number});
Item.scope('dynamicQuery', function() { Item.scope('dynamicQuery', function() {
seed++; seed++;
return { where: { creator: seed }}; return {where: {creator: seed}};
}); });
}); });
beforeEach(function(done) { beforeEach(function(done) {
Item.create({ title: 1, creator: 1 }, function() { Item.create({title: 1, creator: 1}, function() {
Item.create({ title: 2, creator: 2 }, done); Item.create({title: 2, creator: 2}, done);
}); });
}); });

View File

@ -13,6 +13,8 @@
} }
*/ */
'use strict';
var group_name = false, EXT_EXP; var group_name = false, EXT_EXP;
function it(should, test_case) { function it(should, test_case) {
check_external_exports(); check_external_exports();

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var jdb = require('../'); var jdb = require('../');
var DataSource = jdb.DataSource; var DataSource = jdb.DataSource;
var assert = require('assert'); var assert = require('assert');
@ -19,14 +20,14 @@ describe('Transient connector', function() {
before(function() { before(function() {
db = getTransientDataSource(); db = getTransientDataSource();
TransientModel = db.define('TransientModel', {}, { idInjection: false }); TransientModel = db.define('TransientModel', {}, {idInjection: false});
Person = TransientModel.extend('Person', { name: String }); Person = TransientModel.extend('Person', {name: String});
Person.attachTo(db); Person.attachTo(db);
Widget = db.define('Widget', { name: String }); Widget = db.define('Widget', {name: String});
Item = db.define('Item', { Item = db.define('Item', {
id: { type: Number, id: true }, name: String, id: {type: Number, id: true}, name: String,
}); });
}); });
@ -34,9 +35,9 @@ describe('Transient connector', function() {
should.not.exist(Person.definition.properties.id); should.not.exist(Person.definition.properties.id);
should.exist(Person.definition.properties.name); should.exist(Person.definition.properties.name);
Person.create({ name: 'Wilma' }, function(err, inst) { Person.create({name: 'Wilma'}, function(err, inst) {
should.not.exist(err); should.not.exist(err);
inst.toObject().should.eql({ name: 'Wilma' }); inst.toObject().should.eql({name: 'Wilma'});
Person.count(function(err, count) { Person.count(function(err, count) {
should.not.exist(err); should.not.exist(err);
@ -52,7 +53,7 @@ describe('Transient connector', function() {
Widget.definition.properties.id.type.should.equal(String); Widget.definition.properties.id.type.should.equal(String);
Widget.create({ name: 'Thing' }, function(err, inst) { Widget.create({name: 'Thing'}, function(err, inst) {
should.not.exist(err); should.not.exist(err);
inst.id.should.match(/^[0-9a-fA-F]{24}$/); inst.id.should.match(/^[0-9a-fA-F]{24}$/);
inst.name.should.equal('Thing'); inst.name.should.equal('Thing');
@ -71,7 +72,7 @@ describe('Transient connector', function() {
Item.definition.properties.id.type.should.equal(Number); Item.definition.properties.id.type.should.equal(Number);
Item.create({ name: 'Example' }, function(err, inst) { Item.create({name: 'Example'}, function(err, inst) {
should.not.exist(err); should.not.exist(err);
inst.name.should.equal('Example'); inst.name.should.equal('Example');

View File

@ -3,6 +3,7 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var utils = require('../lib/utils'); var utils = require('../lib/utils');
var fieldsToArray = utils.fieldsToArray; var fieldsToArray = utils.fieldsToArray;
@ -30,10 +31,10 @@ describe('util.fieldsToArray', function() {
sample({}).expect(undefined); sample({}).expect(undefined);
sample('foo').expect(['foo']); sample('foo').expect(['foo']);
sample(['foo']).expect(['foo']); sample(['foo']).expect(['foo']);
sample({ 'foo': 1 }).expect(['foo']); sample({'foo': 1}).expect(['foo']);
sample({ 'bat': true }).expect(['bat']); sample({'bat': true}).expect(['bat']);
sample({ 'bat': 0 }).expect(['foo', 'bar', 'baz']); sample({'bat': 0}).expect(['foo', 'bar', 'baz']);
sample({ 'bat': false }).expect(['foo', 'bar', 'baz']); sample({'bat': false}).expect(['foo', 'bar', 'baz']);
}); });
it('should exclude unknown properties', function() { it('should exclude unknown properties', function() {
@ -43,23 +44,23 @@ describe('util.fieldsToArray', function() {
sample({}, true).expect(undefined); sample({}, true).expect(undefined);
sample('foo', true).expect(['foo']); sample('foo', true).expect(['foo']);
sample(['foo', 'unknown'], true).expect(['foo']); sample(['foo', 'unknown'], true).expect(['foo']);
sample({ 'foo': 1, unknown: 1 }, true).expect(['foo']); sample({'foo': 1, unknown: 1}, true).expect(['foo']);
sample({ 'bat': true, unknown: true }, true).expect(['bat']); sample({'bat': true, unknown: true}, true).expect(['bat']);
sample({ 'bat': 0 }, true).expect(['foo', 'bar', 'baz']); sample({'bat': 0}, true).expect(['foo', 'bar', 'baz']);
sample({ 'bat': false }, true).expect(['foo', 'bar', 'baz']); sample({'bat': false}, true).expect(['foo', 'bar', 'baz']);
}); });
}); });
describe('util.removeUndefined', function() { describe('util.removeUndefined', function() {
it('Remove undefined values from the query object', function() { it('Remove undefined values from the query object', function() {
var q1 = { where: { x: 1, y: undefined }}; var q1 = {where: {x: 1, y: undefined}};
should.deepEqual(removeUndefined(q1), { where: { x: 1 }}); should.deepEqual(removeUndefined(q1), {where: {x: 1}});
var q2 = { where: { x: 1, y: 2 }}; var q2 = {where: {x: 1, y: 2}};
should.deepEqual(removeUndefined(q2), { where: { x: 1, y: 2 }}); should.deepEqual(removeUndefined(q2), {where: {x: 1, y: 2}});
var q3 = { where: { x: 1, y: { in: [2, undefined] }}}; var q3 = {where: {x: 1, y: {in: [2, undefined]}}};
should.deepEqual(removeUndefined(q3), { where: { x: 1, y: { in: [2] }}}); should.deepEqual(removeUndefined(q3), {where: {x: 1, y: {in: [2]}}});
should.equal(removeUndefined(null), null); should.equal(removeUndefined(null), null);
@ -68,14 +69,14 @@ describe('util.removeUndefined', function() {
should.equal(removeUndefined('x'), 'x'); should.equal(removeUndefined('x'), 'x');
var date = new Date(); var date = new Date();
var q4 = { where: { x: 1, y: date }}; var q4 = {where: {x: 1, y: date}};
should.deepEqual(removeUndefined(q4), { where: { x: 1, y: date }}); should.deepEqual(removeUndefined(q4), {where: {x: 1, y: date}});
// test handling of undefined // test handling of undefined
var q5 = { where: { x: 1, y: undefined }}; var q5 = {where: {x: 1, y: undefined}};
should.deepEqual(removeUndefined(q5, 'nullify'), { where: { x: 1, y: null }}); should.deepEqual(removeUndefined(q5, 'nullify'), {where: {x: 1, y: null}});
var q6 = { where: { x: 1, y: undefined }}; var q6 = {where: {x: 1, y: undefined}};
(function() { removeUndefined(q6, 'throw'); }).should.throw(/`undefined` in query/); (function() { removeUndefined(q6, 'throw'); }).should.throw(/`undefined` in query/);
}); });
@ -146,71 +147,71 @@ describe('util.parseSettings', function() {
describe('mergeSettings', function() { describe('mergeSettings', function() {
it('should merge settings correctly', function() { it('should merge settings correctly', function() {
var src = { base: 'User', var src = {base: 'User',
relations: { accessTokens: { model: 'accessToken', type: 'hasMany', relations: {accessTokens: {model: 'accessToken', type: 'hasMany',
foreignKey: 'userId' }, foreignKey: 'userId'},
account: { model: 'account', type: 'belongsTo' }}, account: {model: 'account', type: 'belongsTo'}},
acls: [ acls: [
{ accessType: '*', {accessType: '*',
permission: 'DENY', permission: 'DENY',
principalType: 'ROLE', principalType: 'ROLE',
principalId: '$everyone' }, principalId: '$everyone'},
{ accessType: '*', {accessType: '*',
permission: 'ALLOW', permission: 'ALLOW',
principalType: 'ROLE', principalType: 'ROLE',
property: 'login', property: 'login',
principalId: '$everyone' }, principalId: '$everyone'},
{ permission: 'ALLOW', {permission: 'ALLOW',
property: 'findById', property: 'findById',
principalType: 'ROLE', principalType: 'ROLE',
principalId: '$owner' }, principalId: '$owner'},
] }; ]};
var tgt = { strict: false, var tgt = {strict: false,
acls: [ acls: [
{ principalType: 'ROLE', {principalType: 'ROLE',
principalId: '$everyone', principalId: '$everyone',
permission: 'ALLOW', permission: 'ALLOW',
property: 'create' }, property: 'create'},
{ principalType: 'ROLE', {principalType: 'ROLE',
principalId: '$owner', principalId: '$owner',
permission: 'ALLOW', permission: 'ALLOW',
property: 'removeById' }, property: 'removeById'},
], ],
maxTTL: 31556926, maxTTL: 31556926,
ttl: 1209600 }; ttl: 1209600};
var dst = mergeSettings(tgt, src); var dst = mergeSettings(tgt, src);
var expected = { strict: false, var expected = {strict: false,
acls: [ acls: [
{ principalType: 'ROLE', {principalType: 'ROLE',
principalId: '$everyone', principalId: '$everyone',
permission: 'ALLOW', permission: 'ALLOW',
property: 'create' }, property: 'create'},
{ principalType: 'ROLE', {principalType: 'ROLE',
principalId: '$owner', principalId: '$owner',
permission: 'ALLOW', permission: 'ALLOW',
property: 'removeById' }, property: 'removeById'},
{ accessType: '*', {accessType: '*',
permission: 'DENY', permission: 'DENY',
principalType: 'ROLE', principalType: 'ROLE',
principalId: '$everyone' }, principalId: '$everyone'},
{ accessType: '*', {accessType: '*',
permission: 'ALLOW', permission: 'ALLOW',
principalType: 'ROLE', principalType: 'ROLE',
property: 'login', property: 'login',
principalId: '$everyone' }, principalId: '$everyone'},
{ permission: 'ALLOW', {permission: 'ALLOW',
property: 'findById', property: 'findById',
principalType: 'ROLE', principalType: 'ROLE',
principalId: '$owner' }, principalId: '$owner'},
], ],
maxTTL: 31556926, maxTTL: 31556926,
ttl: 1209600, ttl: 1209600,
base: 'User', base: 'User',
relations: { accessTokens: { model: 'accessToken', type: 'hasMany', relations: {accessTokens: {model: 'accessToken', type: 'hasMany',
foreignKey: 'userId' }, foreignKey: 'userId'},
account: { model: 'account', type: 'belongsTo' }}}; account: {model: 'account', type: 'belongsTo'}}};
should.deepEqual(dst.acls, expected.acls, 'Merged settings should match the expectation'); should.deepEqual(dst.acls, expected.acls, 'Merged settings should match the expectation');
}); });
@ -219,12 +220,12 @@ describe('mergeSettings', function() {
describe('sortObjectsByIds', function() { describe('sortObjectsByIds', function() {
var items = [ var items = [
{ id: 1, name: 'a' }, {id: 1, name: 'a'},
{ id: 2, name: 'b' }, {id: 2, name: 'b'},
{ id: 3, name: 'c' }, {id: 3, name: 'c'},
{ id: 4, name: 'd' }, {id: 4, name: 'd'},
{ id: 5, name: 'e' }, {id: 5, name: 'e'},
{ id: 6, name: 'f' }, {id: 6, name: 'f'},
]; ];
it('should sort', function() { it('should sort', function() {
@ -259,8 +260,8 @@ describe('util.mergeIncludes', function() {
var baseInclude = 'relation1'; var baseInclude = 'relation1';
var updateInclude = 'relation2'; var updateInclude = 'relation2';
var expectedInclude = [ var expectedInclude = [
{ relation2: true }, {relation2: true},
{ relation1: true }, {relation1: true},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
@ -269,18 +270,18 @@ describe('util.mergeIncludes', function() {
var baseInclude = 'relation1'; var baseInclude = 'relation1';
var updateInclude = ['relation2']; var updateInclude = ['relation2'];
var expectedInclude = [ var expectedInclude = [
{ relation2: true }, {relation2: true},
{ relation1: true }, {relation1: true},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
it('Merge string & object values to object', function() { it('Merge string & object values to object', function() {
var baseInclude = ['relation1']; var baseInclude = ['relation1'];
var updateInclude = { relation2: 'relation2Include' }; var updateInclude = {relation2: 'relation2Include'};
var expectedInclude = [ var expectedInclude = [
{ relation2: 'relation2Include' }, {relation2: 'relation2Include'},
{ relation1: true }, {relation1: true},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
@ -289,37 +290,37 @@ describe('util.mergeIncludes', function() {
var baseInclude = ['relation1']; var baseInclude = ['relation1'];
var updateInclude = ['relation2']; var updateInclude = ['relation2'];
var expectedInclude = [ var expectedInclude = [
{ relation2: true }, {relation2: true},
{ relation1: true }, {relation1: true},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
it('Merge array & object values to object', function() { it('Merge array & object values to object', function() {
var baseInclude = ['relation1']; var baseInclude = ['relation1'];
var updateInclude = { relation2: 'relation2Include' }; var updateInclude = {relation2: 'relation2Include'};
var expectedInclude = [ var expectedInclude = [
{ relation2: 'relation2Include' }, {relation2: 'relation2Include'},
{ relation1: true }, {relation1: true},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
it('Merge object & object values to object', function() { it('Merge object & object values to object', function() {
var baseInclude = { relation1: 'relation1Include' }; var baseInclude = {relation1: 'relation1Include'};
var updateInclude = { relation2: 'relation2Include' }; var updateInclude = {relation2: 'relation2Include'};
var expectedInclude = [ var expectedInclude = [
{ relation2: 'relation2Include' }, {relation2: 'relation2Include'},
{ relation1: 'relation1Include' }, {relation1: 'relation1Include'},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
it('Override property collision with update value', function() { it('Override property collision with update value', function() {
var baseInclude = { relation1: 'baseValue' }; var baseInclude = {relation1: 'baseValue'};
var updateInclude = { relation1: 'updateValue' }; var updateInclude = {relation1: 'updateValue'};
var expectedInclude = [ var expectedInclude = [
{ relation1: 'updateValue' }, {relation1: 'updateValue'},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
@ -327,9 +328,9 @@ describe('util.mergeIncludes', function() {
it('Merge string includes & include with relation syntax properly', it('Merge string includes & include with relation syntax properly',
function() { function() {
var baseInclude = 'relation1'; var baseInclude = 'relation1';
var updateInclude = { relation: 'relation1' }; var updateInclude = {relation: 'relation1'};
var expectedInclude = [ var expectedInclude = [
{ relation: 'relation1' }, {relation: 'relation1'},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
@ -338,10 +339,10 @@ describe('util.mergeIncludes', function() {
var baseInclude = 'relation1'; var baseInclude = 'relation1';
var updateInclude = { var updateInclude = {
relation: 'relation1', relation: 'relation1',
scope: { include: 'relation2' }, scope: {include: 'relation2'},
}; };
var expectedInclude = [ var expectedInclude = [
{ relation: 'relation1', scope: { include: 'relation2' }}, {relation: 'relation1', scope: {include: 'relation2'}},
]; ];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
@ -352,39 +353,39 @@ describe('util.mergeIncludes', function() {
var baseInclude = ['relation2']; var baseInclude = ['relation2'];
var updateInclude = { var updateInclude = {
relation: 'relation1', relation: 'relation1',
scope: { include: 'relation2' }, scope: {include: 'relation2'},
}; };
var expectedInclude = [{ var expectedInclude = [{
relation: 'relation1', relation: 'relation1',
scope: { include: 'relation2' }, scope: {include: 'relation2'},
}, { relation2: true }]; }, {relation2: true}];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
//w & w/o relation syntax - collision //w & w/o relation syntax - collision
baseInclude = ['relation1']; baseInclude = ['relation1'];
updateInclude = { relation: 'relation1', scope: { include: 'relation2' }}; updateInclude = {relation: 'relation1', scope: {include: 'relation2'}};
expectedInclude = expectedInclude =
[{ relation: 'relation1', scope: { include: 'relation2' }}]; [{relation: 'relation1', scope: {include: 'relation2'}}];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
//w & w/o relation syntax - collision //w & w/o relation syntax - collision
baseInclude = { relation: 'relation1', scope: { include: 'relation2' }}; baseInclude = {relation: 'relation1', scope: {include: 'relation2'}};
updateInclude = ['relation1']; updateInclude = ['relation1'];
expectedInclude = [{ relation1: true }]; expectedInclude = [{relation1: true}];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
it('Merge includes with mixture of strings, arrays & objects properly', function() { it('Merge includes with mixture of strings, arrays & objects properly', function() {
var baseInclude = ['relation1', { relation2: true }, var baseInclude = ['relation1', {relation2: true},
{ relation: 'relation3', scope: { where: { id: 'some id' }}}, {relation: 'relation3', scope: {where: {id: 'some id'}}},
{ relation: 'relation5', scope: { where: { id: 'some id' }}}, {relation: 'relation5', scope: {where: {id: 'some id'}}},
]; ];
var updateInclude = ['relation4', { relation3: true }, var updateInclude = ['relation4', {relation3: true},
{ relation: 'relation2', scope: { where: { id: 'some id' }}}]; {relation: 'relation2', scope: {where: {id: 'some id'}}}];
var expectedInclude = [{ relation4: true }, { relation3: true }, var expectedInclude = [{relation4: true}, {relation3: true},
{ relation: 'relation2', scope: { where: { id: 'some id' }}}, {relation: 'relation2', scope: {where: {id: 'some id'}}},
{ relation1: true }, {relation1: true},
{ relation: 'relation5', scope: { where: { id: 'some id' }}}]; {relation: 'relation5', scope: {where: {id: 'some id'}}}];
checkInputOutput(baseInclude, updateInclude, expectedInclude); checkInputOutput(baseInclude, updateInclude, expectedInclude);
}); });
}); });

View File

@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
// This test written in mocha+should.js // This test written in mocha+should.js
'use strict';
var should = require('./init.js'); var should = require('./init.js');
var async = require('async'); var async = require('async');
@ -42,8 +43,8 @@ describe('validations', function() {
updatedAt: Date, updatedAt: Date,
}); });
Entry = db.define('Entry', { Entry = db.define('Entry', {
id: { type: 'string', id: true, generated: false }, id: {type: 'string', id: true, generated: false},
name: { type: 'string' }, name: {type: 'string'},
}); });
Entry.validatesUniquenessOf('id'); Entry.validatesUniquenessOf('id');
db.automigrate(done); db.automigrate(done);
@ -65,7 +66,7 @@ describe('validations', function() {
describe('skipping', function() { describe('skipping', function() {
it('should NOT skip when `if` is fulfilled', function() { it('should NOT skip when `if` is fulfilled', function() {
User.validatesPresenceOf('pendingPeriod', { if: 'createdByAdmin' }); User.validatesPresenceOf('pendingPeriod', {if: 'createdByAdmin'});
var user = new User; var user = new User;
user.createdByAdmin = true; user.createdByAdmin = true;
user.isValid().should.be.false; user.isValid().should.be.false;
@ -75,7 +76,7 @@ describe('validations', function() {
}); });
it('should skip when `if` is NOT fulfilled', function() { it('should skip when `if` is NOT fulfilled', function() {
User.validatesPresenceOf('pendingPeriod', { if: 'createdByAdmin' }); User.validatesPresenceOf('pendingPeriod', {if: 'createdByAdmin'});
var user = new User; var user = new User;
user.createdByAdmin = false; user.createdByAdmin = false;
user.isValid().should.be.true; user.isValid().should.be.true;
@ -85,7 +86,7 @@ describe('validations', function() {
}); });
it('should NOT skip when `unless` is fulfilled', function() { it('should NOT skip when `unless` is fulfilled', function() {
User.validatesPresenceOf('pendingPeriod', { unless: 'createdByAdmin' }); User.validatesPresenceOf('pendingPeriod', {unless: 'createdByAdmin'});
var user = new User; var user = new User;
user.createdByAdmin = false; user.createdByAdmin = false;
user.isValid().should.be.false; user.isValid().should.be.false;
@ -95,7 +96,7 @@ describe('validations', function() {
}); });
it('should skip when `unless` is NOT fulfilled', function() { it('should skip when `unless` is NOT fulfilled', function() {
User.validatesPresenceOf('pendingPeriod', { unless: 'createdByAdmin' }); User.validatesPresenceOf('pendingPeriod', {unless: 'createdByAdmin'});
var user = new User; var user = new User;
user.createdByAdmin = true; user.createdByAdmin = true;
user.isValid().should.be.true; user.isValid().should.be.true;
@ -112,7 +113,7 @@ describe('validations', function() {
User.validateAsync('pendingPeriod', function(err, done) { User.validateAsync('pendingPeriod', function(err, done) {
if (!this.pendingPeriod) err(); if (!this.pendingPeriod) err();
done(); done();
}, { if: 'createdByAdmin', code: 'presence', message: 'can\'t be blank' }); }, {if: 'createdByAdmin', code: 'presence', message: 'can\'t be blank'});
var user = new User; var user = new User;
user.createdByAdmin = false; user.createdByAdmin = false;
user.isValid(function(valid) { user.isValid(function(valid) {
@ -126,7 +127,7 @@ describe('validations', function() {
User.validateAsync('pendingPeriod', function(err, done) { User.validateAsync('pendingPeriod', function(err, done) {
if (!this.pendingPeriod) err(); if (!this.pendingPeriod) err();
done(); done();
}, { if: 'createdByAdmin', code: 'presence', message: 'can\'t be blank' }); }, {if: 'createdByAdmin', code: 'presence', message: 'can\'t be blank'});
var user = new User; var user = new User;
user.createdByAdmin = true; user.createdByAdmin = true;
user.isValid(function(valid) { user.isValid(function(valid) {
@ -140,7 +141,7 @@ describe('validations', function() {
User.validateAsync('pendingPeriod', function(err, done) { User.validateAsync('pendingPeriod', function(err, done) {
if (!this.pendingPeriod) err(); if (!this.pendingPeriod) err();
done(); done();
}, { unless: 'createdByAdmin', code: 'presence', message: 'can\'t be blank' }); }, {unless: 'createdByAdmin', code: 'presence', message: 'can\'t be blank'});
var user = new User; var user = new User;
user.createdByAdmin = true; user.createdByAdmin = true;
user.isValid(function(valid) { user.isValid(function(valid) {
@ -154,7 +155,7 @@ describe('validations', function() {
User.validateAsync('pendingPeriod', function(err, done) { User.validateAsync('pendingPeriod', function(err, done) {
if (!this.pendingPeriod) err(); if (!this.pendingPeriod) err();
done(); done();
}, { unless: 'createdByAdmin', code: 'presence', message: 'can\'t be blank' }); }, {unless: 'createdByAdmin', code: 'presence', message: 'can\'t be blank'});
var user = new User; var user = new User;
user.createdByAdmin = false; user.createdByAdmin = false;
user.isValid(function(valid) { user.isValid(function(valid) {
@ -173,7 +174,7 @@ describe('validations', function() {
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create(function(e, u) { User.create(function(e, u) {
should.exist(e); should.exist(e);
User.create({ name: 'Valid' }, function(e, d) { User.create({name: 'Valid'}, function(e, d) {
should.not.exist(e); should.not.exist(e);
done(); done();
}); });
@ -183,7 +184,7 @@ describe('validations', function() {
it('should work on update', function(done) { it('should work on update', function(done) {
delete User.validations; delete User.validations;
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create({ name: 'Valid' }, function(e, d) { User.create({name: 'Valid'}, function(e, d) {
d.updateAttribute('name', null, function(e) { d.updateAttribute('name', null, function(e) {
should.exist(e); should.exist(e);
e.should.be.instanceOf(Error); e.should.be.instanceOf(Error);
@ -201,7 +202,7 @@ describe('validations', function() {
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
// It's important to pass an id value, otherwise DAO falls back // It's important to pass an id value, otherwise DAO falls back
// to regular create() // to regular create()
User.updateOrCreate({ id: 999 }, done); User.updateOrCreate({id: 999}, done);
}); });
it('should be skipped by upsert when disabled via settings', function(done) { it('should be skipped by upsert when disabled via settings', function(done) {
@ -215,7 +216,7 @@ describe('validations', function() {
Customer.settings.validateUpsert = false; Customer.settings.validateUpsert = false;
// It's important to pass an id value, otherwise DAO falls back // It's important to pass an id value, otherwise DAO falls back
// to regular create() // to regular create()
Customer.updateOrCreate({ id: 999 }, done); Customer.updateOrCreate({id: 999}, done);
}); });
}); });
@ -225,7 +226,7 @@ describe('validations', function() {
User.settings.validateUpsert = true; User.settings.validateUpsert = true;
// It's important to pass an id value, otherwise DAO falls back // It's important to pass an id value, otherwise DAO falls back
// to regular create() // to regular create()
User.upsert({ id: 999 }, function(err, u) { User.upsert({id: 999}, function(err, u) {
if (!err) return done(new Error('Validation should have failed.')); if (!err) return done(new Error('Validation should have failed.'));
err.should.be.instanceOf(ValidationError); err.should.be.instanceOf(ValidationError);
done(); done();
@ -280,7 +281,7 @@ describe('validations', function() {
}); });
it('should return validation metadata', function() { it('should return validation metadata', function() {
var expected = { name: [{ validation: 'presence', options: {}}] }; var expected = {name: [{validation: 'presence', options: {}}]};
delete User.validations; delete User.validations;
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
var validations = User.validations; var validations = User.validations;
@ -293,12 +294,12 @@ describe('validations', function() {
it('should work on update with options', function(done) { it('should work on update with options', function(done) {
delete User.validations; delete User.validations;
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create({ name: 'Valid' }, function(e, d) { User.create({name: 'Valid'}, function(e, d) {
d.updateAttribute('name', null, { options: 'options' }, function(e) { d.updateAttribute('name', null, {options: 'options'}, function(e) {
should.exist(e); should.exist(e);
e.should.be.instanceOf(Error); e.should.be.instanceOf(Error);
e.should.be.instanceOf(ValidationError); e.should.be.instanceOf(ValidationError);
d.updateAttribute('name', 'Vasiliy', { options: 'options' }, function(e) { d.updateAttribute('name', 'Vasiliy', {options: 'options'}, function(e) {
should.not.exist(e); should.not.exist(e);
done(); done();
}); });
@ -309,7 +310,7 @@ describe('validations', function() {
it('should work on update without options', function(done) { it('should work on update without options', function(done) {
delete User.validations; delete User.validations;
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create({ name: 'Valid' }, function(e, d) { User.create({name: 'Valid'}, function(e, d) {
d.updateAttribute('name', null, function(e) { d.updateAttribute('name', null, function(e) {
should.exist(e); should.exist(e);
e.should.be.instanceOf(Error); e.should.be.instanceOf(Error);
@ -327,7 +328,7 @@ describe('validations', function() {
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create(function(e, u) { User.create(function(e, u) {
should.exist(e); should.exist(e);
User.create({ name: 'Valid' }, { options: 'options' }, function(e, d) { User.create({name: 'Valid'}, {options: 'options'}, function(e, d) {
should.not.exist(e); should.not.exist(e);
done(); done();
}); });
@ -339,7 +340,7 @@ describe('validations', function() {
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create(function(e, u) { User.create(function(e, u) {
should.exist(e); should.exist(e);
User.create({ name: 'Valid' }, function(e, d) { User.create({name: 'Valid'}, function(e, d) {
should.not.exist(e); should.not.exist(e);
done(); done();
}); });
@ -353,8 +354,8 @@ describe('validations', function() {
User.validatesPresenceOf('name', 'email'); User.validatesPresenceOf('name', 'email');
var validations = User.validations; var validations = User.validations;
validations.name.should.eql([{ validation: 'presence', options: {}}]); validations.name.should.eql([{validation: 'presence', options: {}}]);
validations.email.should.eql([{ validation: 'presence', options: {}}]); validations.email.should.eql([{validation: 'presence', options: {}}]);
var u = new User; var u = new User;
u.isValid().should.not.be.true; u.isValid().should.not.be.true;
@ -383,7 +384,7 @@ describe('validations', function() {
}); });
it('should skip validation by property (if/unless)', function() { it('should skip validation by property (if/unless)', function() {
User.validatesPresenceOf('domain', { unless: 'createdByScript' }); User.validatesPresenceOf('domain', {unless: 'createdByScript'});
var user = new User(getValidAttributes()); var user = new User(getValidAttributes());
user.isValid().should.be.true; user.isValid().should.be.true;
@ -401,12 +402,12 @@ describe('validations', function() {
describe('absence', function() { describe('absence', function() {
it('should validate absence', function() { it('should validate absence', function() {
User.validatesAbsenceOf('reserved', { if: 'locked' }); User.validatesAbsenceOf('reserved', {if: 'locked'});
var u = new User({ reserved: 'foo', locked: true }); var u = new User({reserved: 'foo', locked: true});
u.isValid().should.not.be.true; u.isValid().should.not.be.true;
u.reserved = null; u.reserved = null;
u.isValid().should.be.true; u.isValid().should.be.true;
var u = new User({ reserved: 'foo', locked: false }); var u = new User({reserved: 'foo', locked: false});
u.isValid().should.be.true; u.isValid().should.be.true;
}); });
@ -415,11 +416,11 @@ describe('validations', function() {
describe('uniqueness', function() { describe('uniqueness', function() {
it('should validate uniqueness', function(done) { it('should validate uniqueness', function(done) {
User.validatesUniquenessOf('email'); User.validatesUniquenessOf('email');
var u = new User({ email: 'hey' }); var u = new User({email: 'hey'});
Boolean(u.isValid(function(valid) { Boolean(u.isValid(function(valid) {
valid.should.be.true; valid.should.be.true;
u.save(function() { u.save(function() {
var u2 = new User({ email: 'hey' }); var u2 = new User({email: 'hey'});
u2.isValid(function(valid) { u2.isValid(function(valid) {
valid.should.be.false; valid.should.be.false;
done(); done();
@ -430,7 +431,7 @@ describe('validations', function() {
it('should handle same object modification', function(done) { it('should handle same object modification', function(done) {
User.validatesUniquenessOf('email'); User.validatesUniquenessOf('email');
var u = new User({ email: 'hey' }); var u = new User({email: 'hey'});
Boolean(u.isValid(function(valid) { Boolean(u.isValid(function(valid) {
valid.should.be.true; valid.should.be.true;
u.save(function() { u.save(function() {
@ -450,23 +451,23 @@ describe('validations', function() {
siteId: String, siteId: String,
email: String, email: String,
}); });
SiteUser.validatesUniquenessOf('email', { scopedTo: ['siteId'] }); SiteUser.validatesUniquenessOf('email', {scopedTo: ['siteId']});
async.waterfall([ async.waterfall([
function automigrate(next) { function automigrate(next) {
db.automigrate(next); db.automigrate(next);
}, },
function createSite1User(next) { function createSite1User(next) {
SiteUser.create( SiteUser.create(
{ siteId: 1, email: EMAIL }, {siteId: 1, email: EMAIL},
next); next);
}, },
function createSite2User(user1, next) { function createSite2User(user1, next) {
SiteUser.create( SiteUser.create(
{ siteId: 2, email: EMAIL }, {siteId: 2, email: EMAIL},
next); next);
}, },
function validateDuplicateUser(user2, next) { function validateDuplicateUser(user2, next) {
var user3 = new SiteUser({ siteId: 1, email: EMAIL }); var user3 = new SiteUser({siteId: 1, email: EMAIL});
user3.isValid(function(valid) { user3.isValid(function(valid) {
valid.should.be.false; valid.should.be.false;
next(); next();
@ -482,11 +483,11 @@ describe('validations', function() {
it('should skip blank values', function(done) { it('should skip blank values', function(done) {
User.validatesUniquenessOf('email'); User.validatesUniquenessOf('email');
var u = new User({ email: ' ' }); var u = new User({email: ' '});
Boolean(u.isValid(function(valid) { Boolean(u.isValid(function(valid) {
valid.should.be.true; valid.should.be.true;
u.save(function() { u.save(function() {
var u2 = new User({ email: null }); var u2 = new User({email: null});
u2.isValid(function(valid) { u2.isValid(function(valid) {
valid.should.be.true; valid.should.be.true;
done(); done();
@ -500,7 +501,7 @@ describe('validations', function() {
if: function() { return true; }, if: function() { return true; },
unless: function() { return false; }, unless: function() { return false; },
}); });
var u = new User({ email: 'hello' }); var u = new User({email: 'hello'});
Boolean(u.isValid(function(valid) { Boolean(u.isValid(function(valid) {
valid.should.be.true; valid.should.be.true;
done(); done();
@ -508,8 +509,8 @@ describe('validations', function() {
}); });
it('should work with id property on create', function(done) { it('should work with id property on create', function(done) {
Entry.create({ id: 'entry' }, function(err, entry) { Entry.create({id: 'entry'}, function(err, entry) {
var e = new Entry({ id: 'entry' }); var e = new Entry({id: 'entry'});
Boolean(e.isValid(function(valid) { Boolean(e.isValid(function(valid) {
valid.should.be.false; valid.should.be.false;
done(); done();
@ -532,26 +533,26 @@ describe('validations', function() {
it('should overwrite default blank message with custom format message'); it('should overwrite default blank message with custom format message');
it('should skip missing values when allowing null', function() { it('should skip missing values when allowing null', function() {
User.validatesFormatOf('email', { with: /^\S+@\S+\.\S+$/, allowNull: true }); User.validatesFormatOf('email', {with: /^\S+@\S+\.\S+$/, allowNull: true});
var u = new User({}); var u = new User({});
u.isValid().should.be.true; u.isValid().should.be.true;
}); });
it('should skip null values when allowing null', function() { it('should skip null values when allowing null', function() {
User.validatesFormatOf('email', { with: /^\S+@\S+\.\S+$/, allowNull: true }); User.validatesFormatOf('email', {with: /^\S+@\S+\.\S+$/, allowNull: true});
var u = new User({ email: null }); var u = new User({email: null});
u.isValid().should.be.true; u.isValid().should.be.true;
}); });
it('should not skip missing values', function() { it('should not skip missing values', function() {
User.validatesFormatOf('email', { with: /^\S+@\S+\.\S+$/ }); User.validatesFormatOf('email', {with: /^\S+@\S+\.\S+$/});
var u = new User({}); var u = new User({});
u.isValid().should.be.false; u.isValid().should.be.false;
}); });
it('should not skip null values', function() { it('should not skip null values', function() {
User.validatesFormatOf('email', { with: /^\S+@\S+\.\S+$/ }); User.validatesFormatOf('email', {with: /^\S+@\S+\.\S+$/});
var u = new User({ email: null }); var u = new User({email: null});
u.isValid().should.be.false; u.isValid().should.be.false;
}); });
}); });
@ -576,10 +577,10 @@ describe('validations', function() {
it('should validate using custom sync validation', function() { it('should validate using custom sync validation', function() {
User.validate('email', function(err) { User.validate('email', function(err) {
if (this.email === 'hello') err(); if (this.email === 'hello') err();
}, { code: 'invalid-email' }); }, {code: 'invalid-email'});
var u = new User({ email: 'hello' }); var u = new User({email: 'hello'});
Boolean(u.isValid()).should.be.false; Boolean(u.isValid()).should.be.false;
u.errors.codes.should.eql({ email: ['invalid-email'] }); u.errors.codes.should.eql({email: ['invalid-email']});
}); });
it('should validate and return detailed error messages', function() { it('should validate and return detailed error messages', function() {
@ -589,10 +590,10 @@ describe('validations', function() {
err(false); // false: prevent global error message err(false); // false: prevent global error message
} }
}); });
var u = new User({ email: 'hello' }); var u = new User({email: 'hello'});
Boolean(u.isValid()).should.be.false; Boolean(u.isValid()).should.be.false;
u.errors.should.eql({ email: ['Cannot be `hello`'] }); u.errors.should.eql({email: ['Cannot be `hello`']});
u.errors.codes.should.eql({ email: ['invalid-email'] }); u.errors.codes.should.eql({email: ['invalid-email']});
}); });
it('should validate using custom async validation', function(done) { it('should validate using custom async validation', function(done) {
@ -602,7 +603,7 @@ describe('validations', function() {
if: function() { return true; }, if: function() { return true; },
unless: function() { return false; }, unless: function() { return false; },
}); });
var u = new User({ email: 'hello' }); var u = new User({email: 'hello'});
Boolean(u.isValid(function(valid) { Boolean(u.isValid(function(valid) {
valid.should.be.true; valid.should.be.true;
done(); done();
@ -629,26 +630,26 @@ describe('validations', function() {
it('should truncate long objects', function() { it('should truncate long objects', function() {
ValidationError.maxPropertyStringLength = 12; ValidationError.maxPropertyStringLength = 12;
var err = givenValidationError('prop', { foo: 'bar' }, 'is invalid'); var err = givenValidationError('prop', {foo: 'bar'}, 'is invalid');
getErrorDetails(err) getErrorDetails(err)
.should.equal('`prop` is invalid (value: { foo:... }).'); .should.equal('`prop` is invalid (value: { foo:... }).');
}); });
it('should truncate long arrays', function() { it('should truncate long arrays', function() {
ValidationError.maxPropertyStringLength = 12; ValidationError.maxPropertyStringLength = 12;
var err = givenValidationError('prop', [{ a: 1, b: 2 }], 'is invalid'); var err = givenValidationError('prop', [{a: 1, b: 2}], 'is invalid');
getErrorDetails(err) getErrorDetails(err)
.should.equal('`prop` is invalid (value: [ { a...} ]).'); .should.equal('`prop` is invalid (value: [ { a...} ]).');
}); });
it('should print only top-level object properties', function() { it('should print only top-level object properties', function() {
var err = givenValidationError('prop', { a: { b: 'c' }}, 'is invalid'); var err = givenValidationError('prop', {a: {b: 'c'}}, 'is invalid');
getErrorDetails(err) getErrorDetails(err)
.should.equal('`prop` is invalid (value: { a: [Object] }).'); .should.equal('`prop` is invalid (value: { a: [Object] }).');
}); });
it('should print only top-level props of objects in array', function() { it('should print only top-level props of objects in array', function() {
var err = givenValidationError('prop', [{ a: { b: 'c' }}], 'is invalid'); var err = givenValidationError('prop', [{a: {b: 'c'}}], 'is invalid');
getErrorDetails(err) getErrorDetails(err)
.should.equal('`prop` is invalid (value: [ { a: [Object] } ]).'); .should.equal('`prop` is invalid (value: [ { a: [Object] } ]).');
}); });