Clean up tests
This commit is contained in:
parent
7ac9679c17
commit
ba1703fbea
|
@ -14,8 +14,9 @@
|
||||||
"quotmark": "single",
|
"quotmark": "single",
|
||||||
"regexp": true,
|
"regexp": true,
|
||||||
"undef": true,
|
"undef": true,
|
||||||
"unused": true,
|
"unused": false,
|
||||||
"trailing": true,
|
"trailing": true,
|
||||||
"sub": true,
|
"sub": true,
|
||||||
"maxlen": 80
|
"maxlen": 80,
|
||||||
|
"predef": [ "describe", "beforeEach", "afterEach", "before", "after", "it" ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ module.exports = function(grunt) {
|
||||||
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
|
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
|
||||||
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
|
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
|
||||||
'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
|
'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
|
||||||
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
|
'* Copyright (c) <%= grunt.template.today("yyyy") %> ' +
|
||||||
|
'<%= pkg.author.name %>;' +
|
||||||
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
|
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
|
||||||
// Task configuration.
|
// Task configuration.
|
||||||
jshint: {
|
jshint: {
|
||||||
|
@ -17,7 +18,7 @@ module.exports = function(grunt) {
|
||||||
gruntfile: {
|
gruntfile: {
|
||||||
src: 'Gruntfile.js'
|
src: 'Gruntfile.js'
|
||||||
},
|
},
|
||||||
lib_test: {
|
libTest: {
|
||||||
src: ['lib/**/*.js', 'test/**/*.js']
|
src: ['lib/**/*.js', 'test/**/*.js']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,14 +41,15 @@ function RelationMixin() {
|
||||||
* // Save the new chapter
|
* // Save the new chapter
|
||||||
* chapter.save();
|
* chapter.save();
|
||||||
*
|
*
|
||||||
* // you can also call the Chapter.create method with the `chapters` property which will build a chapter
|
* // you can also call the Chapter.create method with the `chapters` property
|
||||||
* // instance and save the it in the data source.
|
* // which will build a chapter instance and save the it in the data source.
|
||||||
* book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) {
|
* book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) {
|
||||||
* // this callback is optional
|
* // this callback is optional
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* // Query chapters for the book
|
* // Query chapters for the book
|
||||||
* book.chapters(function(err, chapters) { // all chapters with bookId = book.id
|
* book.chapters(function(err, chapters) {
|
||||||
|
* // all chapters with bookId = book.id
|
||||||
* console.log(chapters);
|
* console.log(chapters);
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
|
@ -58,9 +59,11 @@ function RelationMixin() {
|
||||||
* });
|
* });
|
||||||
* });
|
* });
|
||||||
*```
|
*```
|
||||||
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
* @param {Object|String} modelTo Model object (or String name of model) to
|
||||||
|
* which you are creating the relationship.
|
||||||
* @options {Object} parameters Configuration parameters; see below.
|
* @options {Object} parameters Configuration parameters; see below.
|
||||||
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
* @property {String} as Name of the property in the referring model that
|
||||||
|
* corresponds to the foreign key field in the related model.
|
||||||
* @property {String} foreignKey Property name of foreign key field.
|
* @property {String} foreignKey Property name of foreign key field.
|
||||||
* @property {Object} model Model object
|
* @property {Object} model Model object
|
||||||
*/
|
*/
|
||||||
|
@ -71,12 +74,14 @@ RelationMixin.hasMany = function hasMany(modelTo, params) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare "belongsTo" relation that sets up a one-to-one connection with another model, such that each
|
* Declare "belongsTo" relation that sets up a one-to-one connection with
|
||||||
* instance of the declaring model "belongs to" one instance of the other model.
|
* another model, such that each instance of the declaring model "belongs
|
||||||
|
* to" one instance of the other model.
|
||||||
*
|
*
|
||||||
* For example, if an application includes users and posts, and each post can be written by exactly one user.
|
* For example, if an application includes users and posts, and each post can be
|
||||||
* The following code specifies that `Post` has a reference called `author` to the `User` model via the `userId` property of `Post`
|
* written by exactly one user. The following code specifies that `Post` has a
|
||||||
* as the foreign key.
|
* reference called `author` to the `User` model via the `userId` property of
|
||||||
|
* `Post` as the foreign key.
|
||||||
* ```
|
* ```
|
||||||
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
|
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
|
||||||
* ```
|
* ```
|
||||||
|
@ -94,7 +99,8 @@ RelationMixin.hasMany = function hasMany(modelTo, params) {
|
||||||
* ```
|
* ```
|
||||||
* Examples:
|
* Examples:
|
||||||
*
|
*
|
||||||
* Suppose the model Post has a *belongsTo* relationship with User (the author of the post). You could declare it this way:
|
* Suppose the model Post has a *belongsTo* relationship with User (the author
|
||||||
|
* of the post). You could declare it this way:
|
||||||
* ```js
|
* ```js
|
||||||
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
|
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
|
||||||
* ```
|
* ```
|
||||||
|
@ -106,18 +112,22 @@ RelationMixin.hasMany = function hasMany(modelTo, params) {
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* The related object is cached, so if later you try to get again the author, no additional request will be made.
|
* The related object is cached, so if later you try to get again the author, no
|
||||||
* But there is an optional boolean parameter in first position that set whether or not you want to reload the cache:
|
* additional request will be made. But there is an optional boolean parameter
|
||||||
|
* in first position that set whether or not you want to reload the cache:
|
||||||
* ```js
|
* ```js
|
||||||
* post.author(true, function(err, user) {
|
* post.author(true, function(err, user) {
|
||||||
* // The user is reloaded, even if it was already cached.
|
* // The user is reloaded, even if it was already cached.
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
* This optional parameter default value is false, so the related object will be loaded from cache if available.
|
* This optional parameter default value is false, so the related object will
|
||||||
|
* be loaded from cache if available.
|
||||||
*
|
*
|
||||||
* @param {Class|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
* @param {Class|String} modelTo Model object (or String name of model)
|
||||||
|
* to which you are creating the relationship.
|
||||||
* @options {Object} params Configuration parameters; see below.
|
* @options {Object} params Configuration parameters; see below.
|
||||||
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
* @property {String} as Name of the property in the referring model that
|
||||||
|
* corresponds to the foreign key field in the related model.
|
||||||
* @property {String} foreignKey Name of foreign key property.
|
* @property {String} foreignKey Name of foreign key property.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -128,9 +138,10 @@ RelationMixin.belongsTo = function(modelTo, params) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hasAndBelongsToMany relation creates a direct many-to-many connection with another model, with no intervening model.
|
* A hasAndBelongsToMany relation creates a direct many-to-many connection with
|
||||||
* For example, if your application includes users and groups, with each group having many users and each user appearing
|
* another model, with no intervening model. For example, if your application
|
||||||
* in many groups, you could declare the models this way:
|
* includes users and groups, with each group having many users and each user
|
||||||
|
* appearing in many groups, you could declare the models this way:
|
||||||
* ```
|
* ```
|
||||||
* User.hasAndBelongsToMany('groups', {model: Group, foreignKey: 'groupId'});
|
* User.hasAndBelongsToMany('groups', {model: Group, foreignKey: 'groupId'});
|
||||||
* ```
|
* ```
|
||||||
|
@ -151,10 +162,11 @@ RelationMixin.belongsTo = function(modelTo, params) {
|
||||||
* user.groups.remove(group, callback);
|
* user.groups.remove(group, callback);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param {String|Object} modelTo Model object (or String name of model) to which you are creating the relationship.
|
* @param {String|Object} modelTo Model object (or String name of model) to
|
||||||
* the relation
|
* which you are creating the relationship.
|
||||||
* @options {Object} params Configuration parameters; see below.
|
* @options {Object} params Configuration parameters; see below.
|
||||||
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
* @property {String} as Name of the property in the referring model that
|
||||||
|
* corresponds to the foreign key field in the related model.
|
||||||
* @property {String} foreignKey Property name of foreign key field.
|
* @property {String} foreignKey Property name of foreign key field.
|
||||||
* @property {Object} model Model object
|
* @property {Object} model Model object
|
||||||
*/
|
*/
|
||||||
|
@ -202,7 +214,7 @@ function defineRelationProperty(modelClass, def) {
|
||||||
scope.create = function() {
|
scope.create = function() {
|
||||||
return that['__create__' + def.name].apply(that, arguments);
|
return that['__create__' + def.name].apply(that, arguments);
|
||||||
};
|
};
|
||||||
scope.deleteById = destroyById = function() {
|
scope.deleteById = scope.destroyById = function() {
|
||||||
return that['__destroyById__' + def.name].apply(that, arguments);
|
return that['__destroyById__' + def.name].apply(that, arguments);
|
||||||
};
|
};
|
||||||
scope.exists = function() {
|
scope.exists = function() {
|
||||||
|
|
|
@ -24,7 +24,7 @@ function RemoteConnector(settings) {
|
||||||
'cannot initiaze RemoteConnector without a settings object');
|
'cannot initiaze RemoteConnector without a settings object');
|
||||||
this.client = settings.client;
|
this.client = settings.client;
|
||||||
this.adapter = settings.adapter || 'rest';
|
this.adapter = settings.adapter || 'rest';
|
||||||
this.protocol = settings.protocol || 'http'
|
this.protocol = settings.protocol || 'http';
|
||||||
this.root = settings.root || '';
|
this.root = settings.root || '';
|
||||||
this.host = settings.host || 'localhost';
|
this.host = settings.host || 'localhost';
|
||||||
this.port = settings.port || 3000;
|
this.port = settings.port || 3000;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"assert": "^1.1.2",
|
"assert": "^1.1.2",
|
||||||
"grunt": "~0.4.5",
|
"grunt": "~0.4.5",
|
||||||
|
"grunt-cli": "^0.1.13",
|
||||||
"grunt-contrib-jshint": "~0.10.0",
|
"grunt-contrib-jshint": "~0.10.0",
|
||||||
"grunt-mocha-test": "^0.11.0",
|
"grunt-mocha-test": "^0.11.0",
|
||||||
"loopback": "^2.2.0",
|
"loopback": "^2.2.0",
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
var loopback = require('loopback');
|
||||||
|
var remoteConnector = require('..');
|
||||||
|
|
||||||
|
exports.createMemoryDataSource = createMemoryDataSource;
|
||||||
|
exports.createModel = createModel;
|
||||||
|
exports.createRemoteDataSource = createRemoteDataSource;
|
||||||
|
exports.createRestAppAndListen = createRestAppAndListen;
|
||||||
|
exports.getUserProperties = getUserProperties;
|
||||||
|
|
||||||
|
function createRestAppAndListen(port) {
|
||||||
|
var app = loopback();
|
||||||
|
|
||||||
|
app.set('host', '127.0.0.1');
|
||||||
|
if (port) app.set('port', port);
|
||||||
|
|
||||||
|
app.use(loopback.rest());
|
||||||
|
app.locals.handler = app.listen();
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMemoryDataSource() {
|
||||||
|
return loopback.createDataSource({connector: 'memory'});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRemoteDataSource(remoteApp) {
|
||||||
|
return loopback.createDataSource({
|
||||||
|
url: 'http://' + remoteApp.get('host') + ':' + remoteApp.get('port'),
|
||||||
|
connector: remoteConnector
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to create models based on a set of options. May associate or link to an
|
||||||
|
* app.
|
||||||
|
*/
|
||||||
|
function createModel(options) {
|
||||||
|
var Model = loopback.PersistedModel.extend(options.parent, options.properties,
|
||||||
|
options.options);
|
||||||
|
if (options.app) options.app.model(Model);
|
||||||
|
if (options.datasource) Model.attachTo(options.datasource);
|
||||||
|
return Model;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUserProperties() {
|
||||||
|
return {
|
||||||
|
'first': String,
|
||||||
|
'last': String,
|
||||||
|
'age': Number,
|
||||||
|
'password': String,
|
||||||
|
'gender': String,
|
||||||
|
'domain': String,
|
||||||
|
'email': String
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,218 @@
|
||||||
|
var assert = require('assert');
|
||||||
|
var helper = require('./helper');
|
||||||
|
var TaskEmitter = require('strong-task-emitter');
|
||||||
|
|
||||||
|
describe('Model tests', function() {
|
||||||
|
var User;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
User = helper.createModel({
|
||||||
|
parent: 'user',
|
||||||
|
app: helper.createRestAppAndListen(),
|
||||||
|
datasource: helper.createMemoryDataSource(),
|
||||||
|
properties: helper.getUserProperties()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.validatesPresenceOf(properties...)', function() {
|
||||||
|
it('should require a model to include a property to be considered valid',
|
||||||
|
function() {
|
||||||
|
User.validatesPresenceOf('first', 'last', 'age');
|
||||||
|
var joe = new User({first: 'joe'});
|
||||||
|
assert(joe.isValid() === false, 'model should not validate');
|
||||||
|
assert(joe.errors.last, 'should have a missing last error');
|
||||||
|
assert(joe.errors.age, 'should have a missing age error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.validatesLengthOf(property, options)', function() {
|
||||||
|
it('should require a property length to be within a specified range',
|
||||||
|
function() {
|
||||||
|
User.validatesLengthOf('password', {min: 5, message: {min:
|
||||||
|
'Password is too short'}});
|
||||||
|
var joe = new User({password: '1234'});
|
||||||
|
assert(joe.isValid() === false, 'model should not be valid');
|
||||||
|
assert(joe.errors.password, 'should have password error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.validatesInclusionOf(property, options)', function() {
|
||||||
|
it('should require a value for `property` to be in the specified array',
|
||||||
|
function() {
|
||||||
|
User.validatesInclusionOf('gender', {in: ['male', 'female']});
|
||||||
|
var foo = new User({gender: 'bar'});
|
||||||
|
assert(foo.isValid() === false, 'model should not be valid');
|
||||||
|
assert(foo.errors.gender, 'should have gender error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.validatesExclusionOf(property, options)', function() {
|
||||||
|
it('should require a value for `property` to not exist in the specified ' +
|
||||||
|
'array', function() {
|
||||||
|
User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});
|
||||||
|
var foo = new User({domain: 'www'});
|
||||||
|
var bar = new User({domain: 'billing'});
|
||||||
|
var bat = new User({domain: 'admin'});
|
||||||
|
assert(foo.isValid() === false);
|
||||||
|
assert(bar.isValid() === false);
|
||||||
|
assert(bat.isValid() === false);
|
||||||
|
assert(foo.errors.domain, 'model should have a domain error');
|
||||||
|
assert(bat.errors.domain, 'model should have a domain error');
|
||||||
|
assert(bat.errors.domain, 'model should have a domain error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.validatesNumericalityOf(property, options)', function() {
|
||||||
|
it('should require a value for `property` to be a specific type of ' +
|
||||||
|
'`Number`', function() {
|
||||||
|
User.validatesNumericalityOf('age', {int: true});
|
||||||
|
var joe = new User({age: 10.2});
|
||||||
|
assert(joe.isValid() === false);
|
||||||
|
var bob = new User({age: 0});
|
||||||
|
assert(bob.isValid() === true);
|
||||||
|
assert(joe.errors.age, 'model should have an age error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('myModel.isValid()', function() {
|
||||||
|
it('should validate the model instance', function() {
|
||||||
|
User.validatesNumericalityOf('age', {int: true});
|
||||||
|
var user = new User({first: 'joe', age: 'flarg'});
|
||||||
|
var valid = user.isValid();
|
||||||
|
assert(valid === false);
|
||||||
|
assert(user.errors.age, 'model should have age error');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should validate the model asynchronously', function(done) {
|
||||||
|
User.validatesNumericalityOf('age', {int: true});
|
||||||
|
var user = new User({first: 'joe', age: 'flarg'});
|
||||||
|
user.isValid(function(valid) {
|
||||||
|
assert(valid === false);
|
||||||
|
assert(user.errors.age, 'model should have age error');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.create([data], [callback])', function() {
|
||||||
|
it('should create an instance and save to the attached data source',
|
||||||
|
function(done) {
|
||||||
|
User.create({first: 'Joe', last: 'Bob'}, function(err, user) {
|
||||||
|
assert(user instanceof User);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('model.save([options], [callback])', function() {
|
||||||
|
it('should save an instance of a Model to the attached data source',
|
||||||
|
function(done) {
|
||||||
|
var joe = new User({first: 'Joe', last: 'Bob'});
|
||||||
|
joe.save(function(err, user) {
|
||||||
|
assert(user.id);
|
||||||
|
assert(!err);
|
||||||
|
assert(!user.errors);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('model.updateAttributes(data, [callback])', function() {
|
||||||
|
it('should save specified attributes to the attached data source',
|
||||||
|
function(done) {
|
||||||
|
User.create({first: 'joe', age: 100}, function(err, user) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(user.first, 'joe');
|
||||||
|
|
||||||
|
user.updateAttributes({
|
||||||
|
first: 'updatedFirst',
|
||||||
|
last: 'updatedLast'
|
||||||
|
}, function(err, updatedUser) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(updatedUser.first, 'updatedFirst');
|
||||||
|
assert.equal(updatedUser.last, 'updatedLast');
|
||||||
|
assert.equal(updatedUser.age, 100);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.upsert(data, callback)', function() {
|
||||||
|
it('should update when a record with id=data.id is found, insert otherwise',
|
||||||
|
function(done) {
|
||||||
|
User.upsert({first: 'joe', id: 7}, function(err, user) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(user.first, 'joe');
|
||||||
|
|
||||||
|
User.upsert({first: 'bob', id: 7}, function(err, updatedUser) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(updatedUser.first, 'bob');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('model.destroy([callback])', function() {
|
||||||
|
it('should remove a model from the attached data source', function(done) {
|
||||||
|
User.create({first: 'joe', last: 'bob'}, function(err, user) {
|
||||||
|
User.findById(user.id, function(err, foundUser) {
|
||||||
|
assert.equal(user.id, foundUser.id);
|
||||||
|
foundUser.destroy(function() {
|
||||||
|
User.findById(user.id, function(err, notFound) {
|
||||||
|
assert.equal(notFound, null);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.deleteById(id, [callback])', function() {
|
||||||
|
it('should delete a model instance from the attached data source',
|
||||||
|
function(done) {
|
||||||
|
User.create({first: 'joe', last: 'bob'}, function(err, user) {
|
||||||
|
User.deleteById(user.id, function(err) {
|
||||||
|
User.findById(user.id, function(err, notFound) {
|
||||||
|
assert.equal(notFound, null);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.findById(id, callback)', function() {
|
||||||
|
it('should find an instance by id', function(done) {
|
||||||
|
User.create({first: 'michael', last: 'jordan', id: 23}, function() {
|
||||||
|
User.findById(23, function(err, user) {
|
||||||
|
assert.equal(user.id, 23);
|
||||||
|
assert.equal(user.first, 'michael');
|
||||||
|
assert.equal(user.last, 'jordan');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.count([query], callback)', function() {
|
||||||
|
it('should return the count of Model instances in data source',
|
||||||
|
function(done) {
|
||||||
|
var taskEmitter = new TaskEmitter();
|
||||||
|
taskEmitter
|
||||||
|
.task(User, 'create', {first: 'jill', age: 100})
|
||||||
|
.task(User, 'create', {first: 'bob', age: 200})
|
||||||
|
.task(User, 'create', {first: 'jan'})
|
||||||
|
.task(User, 'create', {first: 'sam'})
|
||||||
|
.task(User, 'create', {first: 'suzy'})
|
||||||
|
.on('done', function() {
|
||||||
|
User.count({age: {gt: 99}}, function(err, count) {
|
||||||
|
assert.equal(count, 2);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,122 +1,108 @@
|
||||||
var loopback = require('loopback');
|
|
||||||
var defineModelTestsWithDataSource = require('./util/model-tests');
|
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var Remote = require('..');
|
var helper = require('./helper');
|
||||||
|
|
||||||
function createAppWithRest() {
|
|
||||||
var app = loopback();
|
|
||||||
app.set('host', '127.0.0.1');
|
|
||||||
app.use(loopback.rest());
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
function listenAndSetupRemoteDS(test, app, remoteName, cb) {
|
|
||||||
app.listen(0, function() {
|
|
||||||
test[remoteName] = loopback.createDataSource({
|
|
||||||
host: '127.0.0.1',
|
|
||||||
port: app.get('port'),
|
|
||||||
connector: Remote,
|
|
||||||
});
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('RemoteConnector', function() {
|
describe('RemoteConnector', function() {
|
||||||
var remoteApp;
|
var ctx = this;
|
||||||
var remote;
|
|
||||||
|
|
||||||
defineModelTestsWithDataSource({
|
before(function() {
|
||||||
beforeEach: function(done) {
|
ctx.serverApp = helper.createRestAppAndListen(3001);
|
||||||
var test = this;
|
ctx.ServerModel = helper.createModel({
|
||||||
remoteApp = createAppWithRest();
|
parent: 'TestModel',
|
||||||
listenAndSetupRemoteDS(test, remoteApp, 'dataSource', done);
|
app: ctx.serverApp,
|
||||||
},
|
datasource: helper.createMemoryDataSource()
|
||||||
onDefine: function(Model) {
|
});
|
||||||
var RemoteModel = Model.extend(Model.modelName);
|
ctx.remoteApp = helper.createRestAppAndListen(3002);
|
||||||
RemoteModel.attachTo(loopback.createDataSource({
|
ctx.RemoteModel = helper.createModel({
|
||||||
connector: loopback.Memory
|
parent: 'TestModel',
|
||||||
}));
|
app: ctx.remoteApp,
|
||||||
remoteApp.model(RemoteModel);
|
datasource: helper.createRemoteDataSource(ctx.serverApp)
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function(done) {
|
after(function() {
|
||||||
var test = this;
|
ctx.serverApp.locals.handler.close();
|
||||||
var ServerModel = this.ServerModel =
|
ctx.remoteApp.locals.handler.close();
|
||||||
loopback.PersistedModel.extend('TestModel');
|
ctx.ServerModel = null;
|
||||||
|
ctx.RemoteModel = null;
|
||||||
remoteApp = test.remoteApp = createAppWithRest();
|
|
||||||
remoteApp.model(ServerModel);
|
|
||||||
|
|
||||||
listenAndSetupRemoteDS(test, remoteApp, 'remote', done);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support the save method', function(done) {
|
it('should support the save method', function(done) {
|
||||||
var calledServerCreate = false;
|
var calledServerCreate = false;
|
||||||
var RemoteModel = loopback.PersistedModel.extend('TestModel');
|
|
||||||
RemoteModel.attachTo(this.remote);
|
|
||||||
|
|
||||||
var ServerModel = this.ServerModel;
|
ctx.ServerModel.create = function(data, cb, callback) {
|
||||||
|
|
||||||
ServerModel.create = function(data, cb) {
|
|
||||||
calledServerCreate = true;
|
calledServerCreate = true;
|
||||||
data.id = 1;
|
data.id = 1;
|
||||||
cb(null, data);
|
if (callback) callback(null, data);
|
||||||
}
|
else cb(null, data);
|
||||||
|
};
|
||||||
|
|
||||||
ServerModel.setupRemoting();
|
var m = new ctx.RemoteModel({foo: 'bar'});
|
||||||
|
m.save(function(err, instance) {
|
||||||
var m = new RemoteModel({foo: 'bar'});
|
if (err) return done(err);
|
||||||
m.save(function(err, inst) {
|
assert(instance);
|
||||||
assert(inst instanceof RemoteModel);
|
assert(instance instanceof ctx.RemoteModel);
|
||||||
assert(calledServerCreate);
|
assert(calledServerCreate);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support aliases', function(done) {
|
it('should support aliases', function(done) {
|
||||||
var RemoteModel = loopback.PersistedModel.extend('TestModel');
|
var calledServerUpsert = false;
|
||||||
RemoteModel.attachTo(this.remote);
|
ctx.ServerModel.upsert = function(id, cb) {
|
||||||
|
calledServerUpsert = true;
|
||||||
var ServerModel = this.ServerModel;
|
cb();
|
||||||
|
|
||||||
ServerModel.upsert = function(id, cb) {
|
|
||||||
done();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RemoteModel.updateOrCreate({}, function(err, inst) {
|
ctx.RemoteModel.updateOrCreate({}, function(err, instance) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
assert(instance);
|
||||||
|
assert(instance instanceof ctx.RemoteModel);
|
||||||
|
assert(calledServerUpsert);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Custom Path', function() {
|
describe('Custom Path', function() {
|
||||||
var test = this;
|
var ctx = this;
|
||||||
|
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
var ServerModel = loopback.PersistedModel.extend('TestModel', {}, {
|
ctx.serverApp = helper.createRestAppAndListen(3001);
|
||||||
|
ctx.ServerModel = helper.createModel({
|
||||||
|
parent: 'TestModel',
|
||||||
|
app: ctx.serverApp,
|
||||||
|
datasource: helper.createMemoryDataSource(),
|
||||||
|
options: {
|
||||||
http: {path: '/custom'}
|
http: {path: '/custom'}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server = test.server = createAppWithRest();
|
ctx.remoteApp = helper.createRestAppAndListen(3002);
|
||||||
server.dataSource('db', {
|
ctx.RemoteModel = helper.createModel({
|
||||||
connector: loopback.Memory,
|
parent: 'TestModel',
|
||||||
name: 'db'
|
app: ctx.remoteApp,
|
||||||
|
datasource: helper.createRemoteDataSource(ctx.serverApp),
|
||||||
|
options: {
|
||||||
|
dataSource: 'remote',
|
||||||
|
http: {path: '/custom'}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
server.model(ServerModel, {dataSource: 'db'});
|
|
||||||
|
|
||||||
listenAndSetupRemoteDS(test, server, 'remote', done);
|
after(function(done)
|
||||||
|
{
|
||||||
|
ctx.serverApp.locals.handler.close();
|
||||||
|
ctx.remoteApp.locals.handler.close();
|
||||||
|
ctx.ServerModel = null;
|
||||||
|
ctx.RemoteModel = null;
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support http.path configuration', function(done) {
|
it('should support http.path configuration', function(done) {
|
||||||
var RemoteModel = loopback.PersistedModel.extend('TestModel', {}, {
|
ctx.RemoteModel.create({}, function(err, instance) {
|
||||||
dataSource: 'remote',
|
if (err) return done(err);
|
||||||
http: {path: '/custom'}
|
assert(instance);
|
||||||
});
|
|
||||||
RemoteModel.attachTo(test.remote);
|
|
||||||
|
|
||||||
RemoteModel.create({}, function(err, instance) {
|
|
||||||
if (err) return assert(err);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
var assert = require('assert');
|
||||||
|
var helper = require('./helper');
|
||||||
|
var TaskEmitter = require('strong-task-emitter');
|
||||||
|
|
||||||
|
describe('Remote model tests', function() {
|
||||||
|
var ctx = this;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
ctx.serverApp = helper.createRestAppAndListen(3001);
|
||||||
|
ctx.ServerModel = helper.createModel({
|
||||||
|
parent: 'TestModel',
|
||||||
|
app: ctx.serverApp,
|
||||||
|
datasource: helper.createMemoryDataSource(),
|
||||||
|
properties: helper.userProperties
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.remoteApp = helper.createRestAppAndListen(3002);
|
||||||
|
ctx.RemoteModel = helper.createModel({
|
||||||
|
parent: 'TestModel',
|
||||||
|
app: ctx.remoteApp,
|
||||||
|
datasource: helper.createRemoteDataSource(ctx.serverApp),
|
||||||
|
properties: helper.userProperties
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
ctx.serverApp.locals.handler.close();
|
||||||
|
ctx.remoteApp.locals.handler.close();
|
||||||
|
ctx.ServerModel = null;
|
||||||
|
ctx.RemoteModel = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.create([data], [callback])', function() {
|
||||||
|
it('should create an instance and save to the attached data source',
|
||||||
|
function(done) {
|
||||||
|
ctx.RemoteModel.create({first: 'Joe', last: 'Bob'}, function(err, user) {
|
||||||
|
assert(user instanceof ctx.RemoteModel);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('model.save([options], [callback])', function() {
|
||||||
|
it('should save an instance of a Model to the attached data source',
|
||||||
|
function(done) {
|
||||||
|
var joe = new ctx.RemoteModel({first: 'Joe', last: 'Bob'});
|
||||||
|
joe.save(function(err, user) {
|
||||||
|
assert(user.id);
|
||||||
|
assert(!err);
|
||||||
|
assert(!user.errors);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('model.updateAttributes(data, [callback])', function() {
|
||||||
|
it('should save specified attributes to the attached data source',
|
||||||
|
function(done) {
|
||||||
|
ctx.ServerModel.create({first: 'joe', age: 100}, function(err, user) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(user.first, 'joe');
|
||||||
|
|
||||||
|
user.updateAttributes({
|
||||||
|
first: 'updatedFirst',
|
||||||
|
last: 'updatedLast'
|
||||||
|
}, function(err, updatedUser) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(updatedUser.first, 'updatedFirst');
|
||||||
|
assert.equal(updatedUser.last, 'updatedLast');
|
||||||
|
assert.equal(updatedUser.age, 100);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.upsert(data, callback)', function() {
|
||||||
|
it('should update when a record with id=data.id is found, insert otherwise',
|
||||||
|
function(done) {
|
||||||
|
ctx.RemoteModel.upsert({first: 'joe', id: 7}, function(err, user) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(user.first, 'joe');
|
||||||
|
|
||||||
|
ctx.RemoteModel.upsert({first: 'bob', id: 7}, function(err,
|
||||||
|
updatedUser) {
|
||||||
|
assert(!err);
|
||||||
|
assert.equal(updatedUser.first, 'bob');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.deleteById(id, [callback])', function() {
|
||||||
|
it('should delete a model instance from the attached data source',
|
||||||
|
function(done) {
|
||||||
|
ctx.ServerModel.create({first: 'joe', last: 'bob'}, function(err, user) {
|
||||||
|
ctx.RemoteModel.deleteById(user.id, function(err) {
|
||||||
|
ctx.RemoteModel.findById(user.id, function(err, notFound) {
|
||||||
|
assert.equal(notFound, null);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.findById(id, callback)', function() {
|
||||||
|
it('should find an instance by id from the attached data source',
|
||||||
|
function(done) {
|
||||||
|
ctx.ServerModel.create({first: 'michael', last: 'jordan', id: 23},
|
||||||
|
function() {
|
||||||
|
ctx.RemoteModel.findById(23, function(err, user) {
|
||||||
|
assert.equal(user.id, 23);
|
||||||
|
assert.equal(user.first, 'michael');
|
||||||
|
assert.equal(user.last, 'jordan');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Model.count([query], callback)', function() {
|
||||||
|
it('should return the count of Model instances from both data source',
|
||||||
|
function(done) {
|
||||||
|
var taskEmitter = new TaskEmitter();
|
||||||
|
taskEmitter
|
||||||
|
.task(ctx.ServerModel, 'create', {first: 'jill', age: 100})
|
||||||
|
.task(ctx.RemoteModel, 'create', {first: 'bob', age: 200})
|
||||||
|
.task(ctx.RemoteModel, 'create', {first: 'jan'})
|
||||||
|
.task(ctx.ServerModel, 'create', {first: 'sam'})
|
||||||
|
.task(ctx.ServerModel, 'create', {first: 'suzy'})
|
||||||
|
.on('done', function() {
|
||||||
|
ctx.RemoteModel.count({age: {gt: 99}}, function(err, count) {
|
||||||
|
assert.equal(count, 2);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,259 +0,0 @@
|
||||||
var assert = require('assert');
|
|
||||||
var loopback = require('loopback');
|
|
||||||
var PersistedModel = loopback.PersistedModel;
|
|
||||||
var TaskEmitter = require('strong-task-emitter');
|
|
||||||
|
|
||||||
module.exports = function defineModelTestsWithDataSource(options) {
|
|
||||||
|
|
||||||
describe('Model Tests', function() {
|
|
||||||
|
|
||||||
var User, dataSource;
|
|
||||||
|
|
||||||
if (options.beforeEach) {
|
|
||||||
beforeEach(options.beforeEach);
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
var test = this;
|
|
||||||
|
|
||||||
// setup a model / datasource
|
|
||||||
dataSource =
|
|
||||||
this.dataSource || loopback.createDataSource(options.dataSource);
|
|
||||||
|
|
||||||
var extend = PersistedModel.extend;
|
|
||||||
|
|
||||||
// create model hook
|
|
||||||
PersistedModel.extend = function() {
|
|
||||||
var extendedModel = extend.apply(PersistedModel, arguments);
|
|
||||||
|
|
||||||
if (options.onDefine) {
|
|
||||||
options.onDefine.call(test, extendedModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return extendedModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
User = PersistedModel.extend('user', {
|
|
||||||
'first': String,
|
|
||||||
'last': String,
|
|
||||||
'age': Number,
|
|
||||||
'password': String,
|
|
||||||
'gender': String,
|
|
||||||
'domain': String,
|
|
||||||
'email': String
|
|
||||||
}, {
|
|
||||||
trackChanges: true
|
|
||||||
});
|
|
||||||
|
|
||||||
// enable destroy all for testing
|
|
||||||
User.destroyAll.shared = true;
|
|
||||||
User.attachTo(dataSource);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.validatesPresenceOf(properties...)', function() {
|
|
||||||
it("Require a model to include a property to be considered valid",
|
|
||||||
function() {
|
|
||||||
User.validatesPresenceOf('first', 'last', 'age');
|
|
||||||
var joe = new User({first: 'joe'});
|
|
||||||
assert(joe.isValid() === false, 'model should not validate');
|
|
||||||
assert(joe.errors.last, 'should have a missing last error');
|
|
||||||
assert(joe.errors.age, 'should have a missing age error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.validatesLengthOf(property, options)', function() {
|
|
||||||
it("Require a property length to be within a specified range",
|
|
||||||
function() {
|
|
||||||
User.validatesLengthOf('password',
|
|
||||||
{min: 5, message: {min: 'Password is too short'}});
|
|
||||||
var joe = new User({password: '1234'});
|
|
||||||
assert(joe.isValid() === false, 'model should not be valid');
|
|
||||||
assert(joe.errors.password, 'should have password error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.validatesInclusionOf(property, options)', function() {
|
|
||||||
it("Require a value for `property` to be in the specified array",
|
|
||||||
function() {
|
|
||||||
User.validatesInclusionOf('gender', {in: ['male', 'female']});
|
|
||||||
var foo = new User({gender: 'bar'});
|
|
||||||
assert(foo.isValid() === false, 'model should not be valid');
|
|
||||||
assert(foo.errors.gender, 'should have gender error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.validatesExclusionOf(property, options)', function() {
|
|
||||||
it("Require a value for `property` to not exist in the specified array",
|
|
||||||
function() {
|
|
||||||
User.validatesExclusionOf('domain',
|
|
||||||
{in: ['www', 'billing', 'admin']});
|
|
||||||
var foo = new User({domain: 'www'});
|
|
||||||
var bar = new User({domain: 'billing'});
|
|
||||||
var bat = new User({domain: 'admin'});
|
|
||||||
assert(foo.isValid() === false);
|
|
||||||
assert(bar.isValid() === false);
|
|
||||||
assert(bat.isValid() === false);
|
|
||||||
assert(foo.errors.domain, 'model should have a domain error');
|
|
||||||
assert(bat.errors.domain, 'model should have a domain error');
|
|
||||||
assert(bat.errors.domain, 'model should have a domain error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.validatesNumericalityOf(property, options)', function() {
|
|
||||||
it("Require a value for `property` to be a specific type of `Number`",
|
|
||||||
function() {
|
|
||||||
User.validatesNumericalityOf('age', {int: true});
|
|
||||||
var joe = new User({age: 10.2});
|
|
||||||
assert(joe.isValid() === false);
|
|
||||||
var bob = new User({age: 0});
|
|
||||||
assert(bob.isValid() === true);
|
|
||||||
assert(joe.errors.age, 'model should have an age error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('myModel.isValid()', function() {
|
|
||||||
it("Validate the model instance", function() {
|
|
||||||
User.validatesNumericalityOf('age', {int: true});
|
|
||||||
var user = new User({first: 'joe', age: 'flarg'})
|
|
||||||
var valid = user.isValid();
|
|
||||||
assert(valid === false);
|
|
||||||
assert(user.errors.age, 'model should have age error');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Asynchronously validate the model', function(done) {
|
|
||||||
User.validatesNumericalityOf('age', {int: true});
|
|
||||||
var user = new User({first: 'joe', age: 'flarg'});
|
|
||||||
user.isValid(function(valid) {
|
|
||||||
assert(valid === false);
|
|
||||||
assert(user.errors.age, 'model should have age error');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.create([data], [callback])', function() {
|
|
||||||
it("Create an instance of Model with given data and save to the attached data source",
|
|
||||||
function(done) {
|
|
||||||
User.create({first: 'Joe', last: 'Bob'}, function(err, user) {
|
|
||||||
assert(user instanceof User);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('model.save([options], [callback])', function() {
|
|
||||||
it("Save an instance of a Model to the attached data source",
|
|
||||||
function(done) {
|
|
||||||
var joe = new User({first: 'Joe', last: 'Bob'});
|
|
||||||
joe.save(function(err, user) {
|
|
||||||
assert(user.id);
|
|
||||||
assert(!err);
|
|
||||||
assert(!user.errors);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('model.updateAttributes(data, [callback])', function() {
|
|
||||||
it("Save specified attributes to the attached data source",
|
|
||||||
function(done) {
|
|
||||||
User.create({first: 'joe', age: 100}, function(err, user) {
|
|
||||||
assert(!err);
|
|
||||||
assert.equal(user.first, 'joe');
|
|
||||||
|
|
||||||
user.updateAttributes({
|
|
||||||
first: 'updatedFirst',
|
|
||||||
last: 'updatedLast'
|
|
||||||
}, function(err, updatedUser) {
|
|
||||||
assert(!err);
|
|
||||||
assert.equal(updatedUser.first, 'updatedFirst');
|
|
||||||
assert.equal(updatedUser.last, 'updatedLast');
|
|
||||||
assert.equal(updatedUser.age, 100);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.upsert(data, callback)', function() {
|
|
||||||
it("Update when record with id=data.id found, insert otherwise",
|
|
||||||
function(done) {
|
|
||||||
User.upsert({first: 'joe', id: 7}, function(err, user) {
|
|
||||||
assert(!err);
|
|
||||||
assert.equal(user.first, 'joe');
|
|
||||||
|
|
||||||
User.upsert({first: 'bob', id: 7}, function(err, updatedUser) {
|
|
||||||
assert(!err);
|
|
||||||
assert.equal(updatedUser.first, 'bob');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('model.destroy([callback])', function() {
|
|
||||||
it("Remove a model from the attached data source", function(done) {
|
|
||||||
User.create({first: 'joe', last: 'bob'}, function(err, user) {
|
|
||||||
User.findById(user.id, function(err, foundUser) {
|
|
||||||
assert.equal(user.id, foundUser.id);
|
|
||||||
foundUser.destroy(function() {
|
|
||||||
User.findById(user.id, function(err, notFound) {
|
|
||||||
assert.equal(notFound, null);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.deleteById(id, [callback])', function() {
|
|
||||||
it("Delete a model instance from the attached data source",
|
|
||||||
function(done) {
|
|
||||||
User.create({first: 'joe', last: 'bob'}, function(err, user) {
|
|
||||||
User.deleteById(user.id, function(err) {
|
|
||||||
User.findById(user.id, function(err, notFound) {
|
|
||||||
assert.equal(notFound, null);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.findById(id, callback)', function() {
|
|
||||||
it("Find an instance by id", function(done) {
|
|
||||||
User.create({first: 'michael', last: 'jordan', id: 23}, function() {
|
|
||||||
User.findById(23, function(err, user) {
|
|
||||||
assert.equal(user.id, 23);
|
|
||||||
assert.equal(user.first, 'michael');
|
|
||||||
assert.equal(user.last, 'jordan');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Model.count([query], callback)', function() {
|
|
||||||
it("Query count of Model instances in data source", function(done) {
|
|
||||||
(new TaskEmitter()).task(User,
|
|
||||||
'create',
|
|
||||||
{first: 'jill', age: 100}).task(User,
|
|
||||||
'create',
|
|
||||||
{first: 'bob', age: 200}).task(User,
|
|
||||||
'create',
|
|
||||||
{first: 'jan'}).task(User, 'create', {first: 'sam'}).task(User,
|
|
||||||
'create',
|
|
||||||
{first: 'suzy'}).on('done', function() {
|
|
||||||
User.count({age: {gt: 99}}, function(err, count) {
|
|
||||||
assert.equal(count, 2);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue