2013-06-07 19:57:51 +00:00
describe ( 'Model' , function ( ) {
2013-06-12 22:44:38 +00:00
var User , memory ;
beforeEach ( function ( ) {
memory = asteroid . createDataSource ( { connector : asteroid . Memory } ) ;
User = memory . createModel ( 'user' , {
'first' : String ,
'last' : String ,
'age' : Number ,
'password' : String ,
'gender' : String ,
'domain' : String ,
'email' : String
} ) ;
2013-06-24 19:26:46 +00:00
} ) ;
2013-06-12 22:44:38 +00:00
2013-06-07 19:57:51 +00:00
describe ( 'Model.validatesPresenceOf(properties...)' , function ( ) {
2013-06-12 22:44:38 +00:00
it ( "Require a model to include a property to be considered valid." , function ( ) {
2013-06-07 19:57:51 +00:00
User . validatesPresenceOf ( 'first' , 'last' , 'age' ) ;
2013-06-12 22:44:38 +00:00
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' ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
describe ( 'Model.validatesLengthOf(property, options)' , function ( ) {
2013-06-12 22:44:38 +00:00
it ( "Require a property length to be within a specified range." , function ( ) {
2013-06-07 19:57:51 +00:00
User . validatesLengthOf ( 'password' , { min : 5 , message : { min : 'Password is too short' } } ) ;
2013-06-12 22:44:38 +00:00
var joe = new User ( { password : '1234' } ) ;
assert ( joe . isValid ( ) === false , 'model should not be valid' ) ;
assert ( joe . errors . password , 'should have password error' ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
describe ( 'Model.validatesInclusionOf(property, options)' , function ( ) {
2013-06-12 22:44:38 +00:00
it ( "Require a value for `property` to be in the specified array." , function ( ) {
2013-06-07 19:57:51 +00:00
User . validatesInclusionOf ( 'gender' , { in : [ 'male' , 'female' ] } ) ;
2013-06-12 22:44:38 +00:00
var foo = new User ( { gender : 'bar' } ) ;
assert ( foo . isValid ( ) === false , 'model should not be valid' ) ;
assert ( foo . errors . gender , 'should have gender error' ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
describe ( 'Model.validatesExclusionOf(property, options)' , function ( ) {
2013-06-12 22:44:38 +00:00
it ( "Require a value for `property` to not exist in the specified array." , function ( ) {
2013-06-07 19:57:51 +00:00
User . validatesExclusionOf ( 'domain' , { in : [ 'www' , 'billing' , 'admin' ] } ) ;
2013-06-12 22:44:38 +00:00
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' ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
describe ( 'Model.validatesNumericalityOf(property, options)' , function ( ) {
2013-06-12 22:44:38 +00:00
it ( "Require a value for `property` to be a specific type of `Number`." , function ( ) {
2013-06-07 19:57:51 +00:00
User . validatesNumericalityOf ( 'age' , { int : true } ) ;
2013-06-12 22:44:38 +00:00
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' ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
describe ( 'Model.validatesUniquenessOf(property, options)' , function ( ) {
it ( "Ensure the value for `property` is unique." , function ( done ) {
User . validatesUniquenessOf ( 'email' , { message : 'email is not unique' } ) ;
2013-06-12 22:44:38 +00:00
var joe = new User ( { email : 'joe@joe.com' } ) ;
var joe2 = new User ( { email : 'joe@joe.com' } ) ;
joe . save ( function ( ) {
joe2 . save ( function ( err ) {
assert ( err , 'should get a validation error' ) ;
assert ( joe2 . errors . email , 'model should have email error' ) ;
done ( ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
describe ( 'myModel.isValid()' , function ( ) {
2013-06-12 22:44:38 +00:00
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' ) ;
2013-06-07 19:57:51 +00:00
} ) ;
2013-06-21 23:41:33 +00:00
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 ( ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
describe ( 'Model.attachTo(dataSource)' , function ( ) {
2013-06-12 22:44:38 +00:00
it ( "Attach a model to a [DataSource](#data-source)" , function ( ) {
var MyModel = asteroid . createModel ( 'my-model' , { name : String } ) ;
2013-06-24 19:26:46 +00:00
assert ( MyModel . find === undefined , 'should not have data access methods' ) ;
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
MyModel . attachTo ( memory ) ;
2013-06-24 19:26:46 +00:00
assert ( typeof MyModel . find === 'function' , 'should have data access methods after attaching to a data source' ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
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 ) {
2013-06-12 22:44:38 +00:00
assert ( user instanceof User ) ;
done ( ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
} ) ;
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 ) {
2013-06-12 22:44:38 +00:00
assert ( user . id ) ;
assert ( ! err ) ;
assert ( ! user . errors ) ;
done ( ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
} ) ;
describe ( 'model.updateAttributes(data, [callback])' , function ( ) {
it ( "Save specified attributes to the attached data source." , function ( done ) {
2013-06-12 22:44:38 +00:00
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 ( ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
2013-06-12 22:44:38 +00:00
describe ( 'Model.upsert(data, callback)' , function ( ) {
2013-06-07 19:57:51 +00:00
it ( "Update when record with id=data.id found, insert otherwise" , function ( done ) {
2013-06-12 22:44:38 +00:00
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 ( ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
describe ( 'model.destroy([callback])' , function ( ) {
it ( "Remove a model from the attached data source." , function ( done ) {
2013-06-12 22:44:38 +00:00
User . create ( { first : 'joe' , last : 'bob' } , function ( err , user ) {
2013-06-24 19:26:46 +00:00
User . findById ( user . id , function ( err , foundUser ) {
2013-06-12 22:44:38 +00:00
assert . equal ( user . id , foundUser . id ) ;
foundUser . destroy ( function ( ) {
2013-06-24 19:26:46 +00:00
User . findById ( user . id , function ( err , notFound ) {
2013-06-12 22:44:38 +00:00
assert ( ! err ) ;
assert . equal ( notFound , null ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
} ) ;
describe ( 'Model.destroyAll(callback)' , function ( ) {
it ( "Delete all Model instances from data source" , function ( done ) {
2013-06-12 22:44:38 +00:00
( new TaskEmitter ( ) )
. task ( User , 'create' , { first : 'jill' } )
. task ( User , 'create' , { first : 'bob' } )
. task ( User , 'create' , { first : 'jan' } )
. task ( User , 'create' , { first : 'sam' } )
. task ( User , 'create' , { first : 'suzy' } )
. on ( 'done' , function ( ) {
User . count ( function ( err , count ) {
assert . equal ( count , 5 ) ;
User . destroyAll ( function ( ) {
User . count ( function ( err , count ) {
assert . equal ( count , 0 ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
2013-06-24 19:26:46 +00:00
describe ( 'Model.findById(id, callback)' , function ( ) {
it ( "Find an instance by id." , function ( done ) {
2013-06-12 22:44:38 +00:00
User . create ( { first : 'michael' , last : 'jordan' , id : 23 } , function ( ) {
2013-06-24 19:26:46 +00:00
User . findById ( 23 , function ( err , user ) {
2013-06-12 22:44:38 +00:00
assert . equal ( user . id , 23 ) ;
assert . equal ( user . first , 'michael' ) ;
assert . equal ( user . last , 'jordan' ) ;
done ( ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
} ) ;
describe ( 'Model.count([query], callback)' , function ( ) {
it ( "Query count of Model instances in data source" , function ( done ) {
2013-06-12 22:44:38 +00:00
( 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 ( ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
2013-06-12 22:44:38 +00:00
} ) ;
} ) ;
describe ( 'Remote Methods' , function ( ) {
beforeEach ( function ( ) {
User . login = function ( username , password , fn ) {
if ( username === 'foo' && password === 'bar' ) {
fn ( null , 123 ) ;
} else {
throw new Error ( 'bad username and password!' ) ;
}
2013-06-07 19:57:51 +00:00
}
2013-06-12 22:44:38 +00:00
2013-06-07 19:57:51 +00:00
asteroid . remoteMethod (
User . login ,
{
accepts : [
{ arg : 'username' , type : 'string' , required : true } ,
{ arg : 'password' , type : 'string' , required : true }
] ,
returns : { arg : 'sessionId' , type : 'any' } ,
2013-06-12 22:44:38 +00:00
http : { path : '/sign-in' , verb : 'get' }
2013-06-07 19:57:51 +00:00
}
) ;
2013-06-12 22:44:38 +00:00
app . use ( asteroid . rest ( ) ) ;
app . model ( User ) ;
2013-06-07 19:57:51 +00:00
} ) ;
2013-06-12 22:44:38 +00:00
2013-06-21 23:48:53 +00:00
describe ( 'Example Remote Method' , function ( ) {
it ( 'Call the method using HTTP / REST' , function ( done ) {
2013-06-12 22:44:38 +00:00
request ( app )
. get ( '/users/sign-in?username=foo&password=bar' )
. expect ( 'Content-Type' , /json/ )
. expect ( 200 )
. end ( function ( err , res ) {
if ( err ) return done ( err ) ;
assert ( res . body . $data === 123 ) ;
done ( ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
2013-06-12 22:44:38 +00:00
describe ( 'Model.beforeRemote(name, fn)' , function ( ) {
it ( 'Run a function before a remote method is called by a client.' , function ( done ) {
var hookCalled = false ;
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
User . beforeRemote ( '*.save' , function ( ctx , user , next ) {
hookCalled = true ;
next ( ) ;
} ) ;
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
// invoke save
request ( app )
. post ( '/users' )
. send ( { data : { first : 'foo' , last : 'bar' } } )
. expect ( 'Content-Type' , /json/ )
. expect ( 200 )
. end ( function ( err , res ) {
if ( err ) return done ( err ) ;
assert ( hookCalled , 'hook wasnt called' ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
describe ( 'Model.afterRemote(name, fn)' , function ( ) {
it ( 'Run a function after a remote method is called by a client.' , function ( done ) {
var beforeCalled = false ;
var afterCalled = false ;
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
User . beforeRemote ( '*.save' , function ( ctx , user , next ) {
assert ( ! afterCalled ) ;
beforeCalled = true ;
next ( ) ;
2013-06-07 19:57:51 +00:00
} ) ;
2013-06-12 22:44:38 +00:00
User . afterRemote ( '*.save' , function ( ctx , user , next ) {
assert ( beforeCalled ) ;
afterCalled = true ;
next ( ) ;
2013-06-07 19:57:51 +00:00
} ) ;
2013-06-12 22:44:38 +00:00
// invoke save
request ( app )
. post ( '/users' )
. send ( { data : { first : 'foo' , last : 'bar' } } )
. expect ( 'Content-Type' , /json/ )
. expect ( 200 )
. end ( function ( err , res ) {
if ( err ) return done ( err ) ;
assert ( beforeCalled , 'before hook was not called' ) ;
assert ( afterCalled , 'after hook was not called' ) ;
done ( ) ;
} ) ;
2013-06-07 19:57:51 +00:00
} ) ;
} ) ;
2013-06-12 22:44:38 +00:00
describe ( 'Remote Method invoking context' , function ( ) {
// describe('ctx.user', function() {
// it("The remote user model calling the method remotely", function(done) {
// done(new Error('test not implemented'));
// });
// });
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
describe ( 'ctx.req' , function ( ) {
it ( "The express ServerRequest object" , function ( done ) {
var hookCalled = false ;
User . beforeRemote ( '*.save' , function ( ctx , user , next ) {
hookCalled = true ;
assert ( ctx . req ) ;
assert ( ctx . req . url ) ;
assert ( ctx . req . method ) ;
assert ( ctx . res ) ;
assert ( ctx . res . write ) ;
assert ( ctx . res . end ) ;
next ( ) ;
} ) ;
// invoke save
request ( app )
. post ( '/users' )
. send ( { data : { first : 'foo' , last : 'bar' } } )
. expect ( 'Content-Type' , /json/ )
. expect ( 200 )
. end ( function ( err , res ) {
if ( err ) return done ( err ) ;
assert ( hookCalled ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
describe ( 'ctx.res' , function ( ) {
it ( "The express ServerResponse object" , function ( done ) {
var hookCalled = false ;
User . beforeRemote ( '*.save' , function ( ctx , user , next ) {
hookCalled = true ;
assert ( ctx . req ) ;
assert ( ctx . req . url ) ;
assert ( ctx . req . method ) ;
assert ( ctx . res ) ;
assert ( ctx . res . write ) ;
assert ( ctx . res . end ) ;
next ( ) ;
} ) ;
// invoke save
request ( app )
. post ( '/users' )
. send ( { data : { first : 'foo' , last : 'bar' } } )
. expect ( 'Content-Type' , /json/ )
. expect ( 200 )
. end ( function ( err , res ) {
if ( err ) return done ( err ) ;
assert ( hookCalled ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
} )
2013-06-07 19:57:51 +00:00
} ) ;
2013-06-12 22:44:38 +00:00
describe ( 'Model.hasMany(Model)' , function ( ) {
it ( "Define a one to many relationship." , function ( done ) {
var Book = memory . createModel ( 'book' , { title : String , author : String } ) ;
var Chapter = memory . createModel ( 'chapter' , { title : String } ) ;
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
// by referencing model
Book . hasMany ( Chapter ) ;
2013-06-07 19:57:51 +00:00
2013-06-12 22:44:38 +00:00
Book . create ( { title : 'Into the Wild' , author : 'Jon Krakauer' } , function ( err , book ) {
// using 'chapters' scope for build:
var c = book . chapters . build ( { title : 'Chapter 1' } ) ;
book . chapters . create ( { title : 'Chapter 2' } , function ( ) {
c . save ( function ( ) {
Chapter . count ( { bookId : book . id } , function ( err , count ) {
assert . equal ( count , 2 ) ;
book . chapters ( { where : { title : 'Chapter 1' } } , function ( err , chapters ) {
assert . equal ( chapters . length , 1 ) ;
assert . equal ( chapters [ 0 ] . title , 'Chapter 1' ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
2013-06-06 00:11:21 +00:00
} ) ;
} ) ;
2013-06-11 16:01:44 +00:00
2013-06-12 22:44:38 +00:00
// describe('Model.hasAndBelongsToMany()', function() {
// it("TODO: implement / document", function(done) {
// /* example -
//
// */
// done(new Error('test not implemented'));
// });
// });
2013-06-11 16:01:44 +00:00
2013-06-12 22:44:38 +00:00
// describe('Model.remoteMethods()', function() {
// it("Return a list of enabled remote methods.", function() {
// app.model(User);
// User.remoteMethods(); // ['save', ...]
// });
// });
2013-06-11 16:01:44 +00:00
2013-06-12 22:44:38 +00:00
// describe('Model.availableMethods()', function() {
// it("Returns the currently available api of a model as well as descriptions of any modified behavior or methods from attached data sources.", function(done) {
// /* example -
// User.attachTo(oracle);
// console.log(User.availableMethods());
//
// {
// 'User.all': {
// accepts: [{arg: 'filter', type: 'object', description: '...'}],
// returns: [{arg: 'users', type: ['User']}]
// },
// 'User.find': {
// accepts: [{arg: 'id', type: 'any'}],
// returns: [{arg: 'items', type: 'User'}]
// },
// ...
// }
// var oracle = asteroid.createDataSource({
// connector: 'oracle',
// host: '111.22.333.44',
// database: 'MYDB',
// username: 'username',
// password: 'password'
// });
//
// */
// done(new Error('test not implemented'));
// });
// });
2013-06-11 16:01:44 +00:00
2013-06-12 22:44:38 +00:00
// describe('Model.before(name, fn)', function(){
// it('Run a function before a method is called.', function() {
// // User.before('save', function(user, next) {
// // console.log('about to save', user);
// //
// // next();
// // });
// //
// // User.before('delete', function(user, next) {
// // // prevent all delete calls
// // next(new Error('deleting is disabled'));
// // });
// // User.beforeRemote('save', function(ctx, user, next) {
// // if(ctx.user.id === user.id) {
// // next();
// // } else {
// // next(new Error('must be logged in to update'))
// // }
// // });
//
// throw new Error('not implemented');
// });
// });
//
// describe('Model.after(name, fn)', function(){
// it('Run a function after a method is called.', function() {
//
// throw new Error('not implemented');
// });
// });
2013-06-06 00:11:21 +00:00
} ) ;