abstract
Version:
Abstraction of JavaScript Objects.
463 lines (338 loc) • 14.3 kB
JavaScript
/**
* Abstract Module API Tests
*
* Test the module API.
*
* mocha test/api.js --reporter list --ui exports --watch
*
* @type {*}
*/
module.exports = {
"before": function() {
module.Abstract = require( '../' );
require( 'should' );
},
"Abstract API": {
"settings": {
"can be used at module level.": function() {
module.Abstract.set( 'test', 'value' );
module.Abstract.get( 'test' ).should.equal( 'value' );
},
"can be used at model level.": function() {
var TestModel = require( '../' ).createModel( function TestModel() {
this.set( 'module.test', 'module.value' );
this.get( 'module.test' ).should.equal( 'module.value' );
});
TestModel.get( 'module.test' ).should.equal( 'module.value' );
},
"can be used at instance level.": function() {
var Instance = require( '../' ).createModel( function TestModel() {
this.set( 'module.test', 'module.value' );
this.get( 'module.test' ).should.equal( 'module.value' );
this.defineConstructor( function() {
this.set( 'instance.test', 'instance.value' );
this.get( 'instance.test' ).should.equal( 'instance.value' );
});
}).create();
Instance.set( 'instance2.test', 'instance2.value' );
Instance.get( 'instance.test' ).should.equal( 'instance.value' );
Instance.get( 'instance2.test' ).should.equal( 'instance2.value' );
},
},
"mixin()": function() {
var target = {
original: true
};
var test = require( '../' ).mixin( target );
target.should.have.property( 'createModel' );
target.should.have.property( 'create' );
target.should.have.property( 'defineProperty' );
target.should.have.property( 'defineProperties' );
},
"call()": function() {
var target = {
original: true
};
var call = require( '../' ).call( target );
call.should.be.a( 'object' );
//call.should.have.property( 'createModel' );
//call.should.have.property( 'create' );
//call.should.have.property( 'defineProperty' );
//call.should.have.property( 'defineProperties' );
},
"bind()": function() {
var target = {
original: true
};
var bind = require( '../' ).bind( target );
bind.should.be.a( 'function' );
//target.should.have.property( 'createModel' );
//target.should.have.property( 'create' );
//target.should.have.property( 'defineProperty' );
//target.should.have.property( 'defineProperties' );
},
"apply()": function() {
var target = {
original: true
};
var apply = require( '../' ).call( target );
apply.should.be.a( 'object' );
//target.should.have.property( 'createModel' );
//target.should.have.property( 'create' );
//target.should.have.property( 'defineProperty' );
//target.should.have.property( 'defineProperties' );
},
"extendPrototype() - creates combined object from multiple prototypes.": function() {
//console.log( require( 'async' ) );
var test = require( '../' ).extendPrototype(
require( 'eventemitter2' ).EventEmitter2.prototype,
require( 'async' ),
require( 'net' )
);
// EventEmitter Methods
test.should.have.property( 'emit' );
test.should.have.property( 'on' );
test.should.have.property( 'onAny' );
// Async Methods
test.should.have.property( 'auto' );
test.should.have.property( 'series' );
test.should.have.property( 'queue' );
// Net Methods
test.should.have.property( 'Socket' );
test.should.have.property( 'Stream' );
test.should.have.property( 'Server' );
},
"create() - generates basic Objects.": function() {
var Abstract = module.Abstract;
// Create New Object
var UserModel = { data: Abstract.create( null, {
name: {
value: 'User',
description: 'Model for generating Users.',
watched: true
},
meta: {
value: {
age: undefined,
sex: undefined,
key: undefined
},
description: 'Used for storing majority of user information.'
},
identify: {
value: function identify( say ) { return [ say, this._id, this._type, this._path ]; },
inheritable: false
}
}) };
if( UserModel.data.name !== 'User' ) {
throw new Error( 'Abstract.create() not working right.' );
}
},
"createModel()": {
"has expected methods in the builder": function() {
module.TestModel = require( '../' ).createModel( function TestModel() {
this.should.have.property( 'use' );
this.should.have.property( 'get' );
this.should.have.property( 'set' );
this.should.have.property( 'defineConstructor' );
this.should.have.property( 'defineProperties' );
this.should.have.property( 'defineProperty' );
this.custom_constructor_method = function MyMethod() {};
this.custom_constructor_property = true;
this.prototype.instance_method = function instance_method() {};
Object.defineProperty( this, 'hidden_custom', { value: true, enumerable: false });
});
},
"returns a constructor function with expected methods.": function() {
module.TestModel.should.be.a( 'function' );
module.TestModel.should.have.property( 'create' );
module.TestModel.should.have.property( 'custom_constructor_property', true );
module.TestModel.should.have.property( 'use' );
module.TestModel.should.have.property( 'get' );
module.TestModel.should.have.property( 'set' );
},
"will expose non-enumerable model properties outside of the context": function() {
module.TestModel.should.have.property( 'hidden_custom' );
},
"can be initialized via new Model and returns expected methods": function() {
var Instance1 = module.TestModel.create();
Instance1.should.be.a( 'object' );
Instance1.should.have.property( 'instance_method' );
Instance1.instance_method.should.have.property( 'name', 'instance_method' );
Instance1.should.have.property( 'constructor' );
Instance1.should.have.property( 'properties' );
Instance1.should.have.property( 'get' );
Instance1.should.have.property( 'set' );
Instance1.should.have.property( 'use' );
},
"can inherit functionality via this.use().": function( done ) {
var TestModel = require( '../' ).createModel( function TestModel() {
this.use( require( 'net' ) );
this.use( require( 'net' ) );
this.use( require( 'async' ) );
this.use( require( 'events' ).EventEmitter.prototype );
this.should.have.property( 'auto' );
this.should.have.property( 'queue' );
this.should.have.property( 'on' );
this.should.have.property( 'emit' );
}).once( 'done', done );
TestModel.should.have.property( 'auto' );
TestModel.should.have.property( 'queue' );
TestModel.should.have.property( 'on' );
TestModel.should.have.property( 'emit' );
TestModel.emit( 'done', null );
},
"can inherit module functionality via this.require().": function() {
var TestModel = require( '../' ).createModel( function TestModel() {
// Require and include into chain
this.require( 'net' ) ;
this.require( 'async' );
// Should not throw error
this.require( 'async' );
// Will not throw an error
this.require( 'i-do-not-exist-abracadabra' );
// Include into chain
this.use( require( 'events' ).EventEmitter.prototype );
// In-context tests
this.should.have.property( 'auto' );
this.should.have.property( 'on' );
this.should.have.property( 'createServer' );
});
// Out of context tests
TestModel.should.have.property( 'auto' );
TestModel.should.have.property( 'on' );
TestModel.should.have.property( 'createServer' );
},
"can define instances with this.defineConstructor()": function() {
var TestModel = require( '../' ).createModel( function TestModel() {
this.use( require( 'async' ) );
this.use( require( 'express' ) );
// Test Async and Express methods in model context
this.should.have.property( 'auto' );
this.should.have.property( 'createServer' );
this.defineConstructor( function create() {
this.use( require( 'events' ).EventEmitter.prototype );
// Test Async, Express and now Emitter methods in Instance Constructor
this.should.have.property( 'auto' );
this.should.have.property( 'emit' );
this.should.have.property( 'on' );
this.should.have.property( 'createServer' );
});
});
//console.log( TestModel.defineConstructor );
var Instance0 = TestModel.create();
//console.log( Instance0 );
},
"property setting": {
"[todo] this.properties()": function() {
// Test seting properties with different values
// Lazy
// true
// false
// null
// undefined
// {}
// ECMA5
// { value: true; }
// { value: false; }
// { value: null; }
// { value: undefined; }
// { value: {}; }
},
"[todo] this.defineProperty()": function() {},
"[todo] this.defineProperties()": function() {},
}
},
"can instantiate Models using": {
"Model.create()": function() {
var Abstract = module.Abstract;
var MyModel = Abstract.createModel( function MyModel( MyModel, prototype ) {
MyModel.defineProperties( prototype, { make: 'Chevy', model: 'Tahoe' })
MyModel.defineConstructor( function create( options ) { Abstract.utility.extend( this, options ); });
});
var Instance = MyModel.create({ year: 2010, mileage: 40000 });
Instance.should.be.a( 'object' );
Instance.should.have.property( 'make', 'Chevy' );
Instance.should.have.property( 'model', 'Tahoe' );
Instance.should.have.property( 'year', 2010 );
Instance.should.have.property( 'mileage', 40000 );
},
"new MyModel.create": function() {
var Abstract = module.Abstract;
var MyModel = Abstract.createModel( function MyModel( MyModel, prototype ) {
MyModel.defineProperties( prototype, { make: 'Chevy', model: 'Tahoe' })
MyModel.defineConstructor( function ConstructorTwo( options ) { Abstract.utility.extend( this, options ); });
});
var Instance = new MyModel.ConstructorTwo({ year: 2010, mileage: 40000 });
Instance.should.be.a( 'object' );
Instance.should.have.property( 'make', 'Chevy' );
Instance.should.have.property( 'model', 'Tahoe' );
Instance.should.have.property( 'year', 2010 );
Instance.should.have.property( 'mileage', 40000 );
},
"Model.custom()": function() {
var Abstract = module.Abstract;
var MyModel = Abstract.createModel( function MyModel( MyModel, prototype ) {
MyModel.defineProperties( prototype, { make: 'Chevy', model: 'Tahoe' })
MyModel.custom = MyModel.defineConstructor( function ConstructorThree( options ) { Abstract.utility.extend( this, options ); });
});
var Instance = MyModel.custom({ year: 2010, mileage: 40000 });
Instance.should.be.a( 'object' );
Instance.should.have.property( 'make', 'Chevy' );
Instance.should.have.property( 'model', 'Tahoe' );
Instance.should.have.property( 'year', 2010 );
Instance.should.have.property( 'mileage', 40000 );
},
"new Model.custom()": function() {
var Abstract = module.Abstract;
var MyModel = Abstract.createModel( function MyModel( MyModel, prototype ) {
MyModel.defineProperties( prototype, { make: 'Chevy', model: 'Tahoe' })
MyModel.custom = MyModel.defineConstructor( function ConstructorFour( options ) { Abstract.utility.extend( this, options ); });
});
var Instance = new MyModel.custom({ year: 2010, mileage: 40000 });
Instance.should.be.a( 'object' );
Instance.should.have.property( 'make', 'Chevy' );
Instance.should.have.property( 'model', 'Tahoe' );
Instance.should.have.property( 'year', 2010 );
Instance.should.have.property( 'mileage', 40000 );
}
},
"can set and store default settings": function() {
var Abstract = module.Abstract;
// Set Module Defaults
Abstract.set( 'defaults', {
enumerable: true,
inheritable: true,
writable: true,
configurable: true,
watched: false,
delayed: false
});
Abstract._meta.should.have.property( 'defaults' );
Abstract._meta.defaults.should.have.property( 'enumerable', true );
},
"instantiation honors enumerability settings": function() {
},
"handles 'properties' setting": function() {
var Abstract = module.Abstract;
// Create dummy user
var User = Abstract.create( require( 'Faker' ).Helpers.createCard() );
// Add analyze constructor with constructor properties
Abstract.defineProperty( User, 'analyze', {
value: function Analyze() { this.email.should.equal( User.email ); },
description: 'Analyze the user profile.',
properties: {
reduce: function reduce() {
//console.log( 'reduce', this );
},
invoke: function invoke() {}
}
})
//User.analyze();
User.analyze.reduce();
User.should.have.property( 'analyze' );
User.analyze.should.have.property( 'invoke' );
User.analyze.should.have.property( 'reduce' );
}
}
}