5 changed files with 234 additions and 205 deletions
@ -1,205 +0,0 @@ |
|||
|
|||
|
|||
// var _d = console.log.bind( console, 'dbg: ' );
|
|||
var _d = function(){}; |
|||
var async = require('async'); |
|||
|
|||
|
|||
var pr = console.log; |
|||
|
|||
var INDENT = ' '; |
|||
var STATUS_FLAG = { |
|||
true : '\u001b[32m\u001b[1m' + '✔' + '\u001b[22m\u001b[39m', |
|||
false : '\u001b[31m\u001b[1m' + '✗' + '\u001b[22m\u001b[39m', |
|||
}; |
|||
|
|||
function print( level, item ){ |
|||
var indent = getIndent( level ); |
|||
var status = STATUS_FLAG[ item.isSuccess ]; |
|||
var timeTaken = '(' + ( item.endTime - item.startTime ) + 'ms)'; |
|||
pr( [ indent, status, item.description, timeTaken ].join(' ') ); |
|||
}; |
|||
|
|||
function safeFn( fn ){ |
|||
return function( done ){ |
|||
try{ |
|||
fn( done ) |
|||
} catch( e ){ |
|||
done( e ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function getIndent( level ){ |
|||
return INDENT.repeat( level ); |
|||
} |
|||
|
|||
function mkAsyncFn( fn ){ |
|||
if( fn.length ){ |
|||
return safeFn( fn ); |
|||
} |
|||
return safeFn( function( done ){ |
|||
setTimeout( function(){ |
|||
fn(); |
|||
done(); |
|||
}, 1 ); |
|||
}); |
|||
} |
|||
|
|||
|
|||
|
|||
function ItBlock( description, fn ){ |
|||
this.description = description; |
|||
this.fn = fn; |
|||
this.isSuccess = false; |
|||
} |
|||
|
|||
ItBlock.prototype.run = function( done ){ |
|||
var self = this; |
|||
this.startTime = Date.now(); |
|||
this.fn( function( err ){ |
|||
self.endTime = Date.now(); |
|||
if( !err ){ |
|||
self.isSuccess = true; |
|||
} |
|||
self.print(); |
|||
done( err ); |
|||
}); |
|||
} |
|||
|
|||
ItBlock.prototype.print = function(){ |
|||
print( this.parent.level+1, this ); |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
function DescribeBlock( description, parentBlock ){ |
|||
_d( 'DescribeBlock:init', parentBlock ); |
|||
|
|||
this.description = description || ''; |
|||
this.parent = parentBlock; |
|||
this.level = parentBlock ? parentBlock.level +1 : 0; |
|||
if( parentBlock ){ |
|||
parentBlock.addChild( this ); |
|||
} |
|||
|
|||
this.tasks = []; |
|||
this.children = []; |
|||
this.its = []; |
|||
this.beforeEach = null; |
|||
this.afterEach = null; |
|||
|
|||
this.isSuccess = false; |
|||
} |
|||
|
|||
|
|||
DescribeBlock.prototype.addChild = function( child ){ |
|||
this.children.push( child ); |
|||
this.tasks.push( child ); |
|||
}; |
|||
|
|||
|
|||
DescribeBlock.prototype.addItBlock = function( description, fn ){ |
|||
var itBlock = new ItBlock( description, mkAsyncFn( fn ) ); |
|||
itBlock.parent = this; |
|||
this.its.push( itBlock ); |
|||
this.tasks.push( itBlock ); |
|||
}; |
|||
|
|||
DescribeBlock.prototype.run = function( cb ){ |
|||
var tasks = []; |
|||
var self = this; |
|||
|
|||
if( this.beforeFn ){ tasks.push( this.beforeFn ); } |
|||
|
|||
this.tasks.forEach( function( itBlock ){ |
|||
if( itBlock instanceof ItBlock ){ |
|||
if( this.beforeEachFn ){ tasks.push( this.beforeEachFn ); } |
|||
tasks.push( itBlock.run.bind( itBlock ) ); |
|||
if( this.afterEachFn ){ tasks.push( this.afterEachFn ); } |
|||
} else { |
|||
tasks.push( itBlock.run.bind( itBlock ) ); |
|||
} |
|||
}, this ); |
|||
|
|||
if( this.afterFn ){ tasks.push( this.afterFn ); } |
|||
|
|||
pr( getIndent( this.level) + ' ---' + this.description + '---' ); |
|||
this.startTime = Date.now(); |
|||
return async.waterfall( tasks, function( err ){ |
|||
|
|||
self.endTime = Date.now(); |
|||
if( !err ){ |
|||
self.isSuccess = true; |
|||
} |
|||
self.print(); |
|||
cb && cb( err ); |
|||
}); |
|||
} |
|||
|
|||
|
|||
DescribeBlock.prototype.print = function(){ |
|||
print( this.level, this ); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
function SimpleMocha(){ |
|||
|
|||
this.describe = this.describe.bind( this ); |
|||
this.it = this.it.bind( this ); |
|||
this.before = this.before.bind( this ); |
|||
this.after = this.after.bind( this ); |
|||
this.beforeEach = this.beforeEach.bind( this ); |
|||
this.afterEach = this.afterEach.bind( this ); |
|||
|
|||
this.rootDescribeBlock = new DescribeBlock(); |
|||
this.currentDescribeBlock = this.rootDescribeBlock; |
|||
} |
|||
|
|||
|
|||
SimpleMocha.prototype.describe = function( description, fn ){ |
|||
var parentDescribeBlock = this.currentDescribeBlock; |
|||
var thisDescribeBlock = new DescribeBlock( description, parentDescribeBlock ); |
|||
|
|||
this.currentDescribeBlock = thisDescribeBlock; |
|||
fn(); |
|||
this.currentDescribeBlock = parentDescribeBlock; |
|||
|
|||
if( parentDescribeBlock.parent === undefined ){ |
|||
this.onLoad && this.onLoad(); |
|||
} |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.it = function( description, fn ){ |
|||
this.currentDescribeBlock.addItBlock( description, fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.before = function( fn ){ |
|||
this.currentDescribeBlock.beforeFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.after = function( fn ){ |
|||
this.currentDescribeBlock.afterFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.beforeEach = function( fn ){ |
|||
this.currentDescribeBlock.beforeEachFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.afterEach = function( fn ){ |
|||
this.currentDescribeBlock.afterEachFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.DescribeBlock = DescribeBlock; |
|||
|
|||
|
|||
module.exports = SimpleMocha; |
@ -0,0 +1,87 @@ |
|||
|
|||
var async = require( 'async' ); |
|||
var ItBlock = require( './it-block' ); |
|||
var utils = require( './utils' ); |
|||
var mkAsyncFn = utils.mkAsyncFn; |
|||
var pr = utils.pr; |
|||
var getIndent = utils.getIndent; |
|||
|
|||
function DescribeBlock( description, parentBlock ){ |
|||
this.description = description || ''; |
|||
this.parent = parentBlock; |
|||
this.level = parentBlock ? parentBlock.level +1 : 0; |
|||
if( parentBlock ){ |
|||
parentBlock.addChild( this ); |
|||
} |
|||
|
|||
this.tasks = []; |
|||
this.beforeEach = null; |
|||
this.afterEach = null; |
|||
|
|||
this.isSuccess = false; |
|||
} |
|||
|
|||
DescribeBlock.prototype.__defineGetter__( 'children', function(){ |
|||
return this.tasks.filter( function( task ){ |
|||
return task instanceof DescribeBlock; |
|||
}); |
|||
}); |
|||
|
|||
|
|||
DescribeBlock.prototype.__defineGetter__( 'children', function(){ |
|||
return this.tasks.filter( function( task ){ |
|||
return task instanceof ItBlock; |
|||
}); |
|||
}); |
|||
|
|||
DescribeBlock.prototype.addChild = function( child ){ |
|||
this.tasks.push( child ); |
|||
}; |
|||
|
|||
|
|||
DescribeBlock.prototype.addItBlock = function( description, fn ){ |
|||
var itBlock = new ItBlock( description, mkAsyncFn( fn ) ); |
|||
itBlock.parent = this; |
|||
this.tasks.push( itBlock ); |
|||
}; |
|||
|
|||
|
|||
DescribeBlock.prototype.run = function( cb ){ |
|||
var tasks = []; |
|||
var self = this; |
|||
|
|||
if( this.beforeFn ){ tasks.push( this.beforeFn ); } |
|||
|
|||
this.tasks.forEach( function( itBlock ){ |
|||
if( itBlock instanceof ItBlock ){ |
|||
if( this.beforeEachFn ){ tasks.push( this.beforeEachFn ); } |
|||
tasks.push( itBlock.run.bind( itBlock ) ); |
|||
if( this.afterEachFn ){ tasks.push( this.afterEachFn ); } |
|||
} else { |
|||
tasks.push( itBlock.run.bind( itBlock ) ); |
|||
} |
|||
}, this ); |
|||
|
|||
if( this.afterFn ){ tasks.push( this.afterFn ); } |
|||
|
|||
pr( getIndent( this.level) + ' ---' + this.description + '---' ); |
|||
this.startTime = Date.now(); |
|||
return async.series( tasks, function( err ){ |
|||
|
|||
self.endTime = Date.now(); |
|||
if( !err ){ |
|||
self.isSuccess = true; |
|||
} |
|||
self.print(); |
|||
cb && cb( err ); |
|||
}); |
|||
} |
|||
|
|||
|
|||
DescribeBlock.prototype.print = function(){ |
|||
print( this.level, this ); |
|||
} |
|||
|
|||
|
|||
|
|||
module.exports = DescribeBlock; |
@ -0,0 +1,30 @@ |
|||
|
|||
|
|||
function ItBlock( description, fn ){ |
|||
this.description = description; |
|||
this.fn = fn; |
|||
this.isSuccess = false; |
|||
} |
|||
|
|||
|
|||
ItBlock.prototype.run = function( done ){ |
|||
var self = this; |
|||
this.startTime = Date.now(); |
|||
this.fn( function( err ){ |
|||
self.endTime = Date.now(); |
|||
if( !err ){ |
|||
self.isSuccess = true; |
|||
} |
|||
self.print(); |
|||
done( err ); |
|||
}); |
|||
} |
|||
|
|||
|
|||
ItBlock.prototype.print = function(){ |
|||
print( this.parent.level+1, this ); |
|||
}; |
|||
|
|||
|
|||
|
|||
module.exports = ItBlock; |
@ -0,0 +1,60 @@ |
|||
|
|||
|
|||
var DescribeBlock = require( './describe-block' ); |
|||
var mkAsyncFn = require( './utils' ).mkAsyncFn; |
|||
|
|||
|
|||
function SimpleMocha(){ |
|||
|
|||
this.describe = this.describe.bind( this ); |
|||
this.it = this.it.bind( this ); |
|||
this.before = this.before.bind( this ); |
|||
this.after = this.after.bind( this ); |
|||
this.beforeEach = this.beforeEach.bind( this ); |
|||
this.afterEach = this.afterEach.bind( this ); |
|||
|
|||
this.rootDescribeBlock = new DescribeBlock(); |
|||
this.currentDescribeBlock = this.rootDescribeBlock; |
|||
} |
|||
|
|||
|
|||
SimpleMocha.prototype.describe = function( description, fn ){ |
|||
var parentDescribeBlock = this.currentDescribeBlock; |
|||
var thisDescribeBlock = new DescribeBlock( description, parentDescribeBlock ); |
|||
|
|||
this.currentDescribeBlock = thisDescribeBlock; |
|||
fn(); |
|||
this.currentDescribeBlock = parentDescribeBlock; |
|||
|
|||
if( parentDescribeBlock.parent === undefined ){ |
|||
this.onLoad && this.onLoad(); |
|||
} |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.it = function( description, fn ){ |
|||
this.currentDescribeBlock.addItBlock( description, fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.before = function( fn ){ |
|||
this.currentDescribeBlock.beforeFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.after = function( fn ){ |
|||
this.currentDescribeBlock.afterFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.beforeEach = function( fn ){ |
|||
this.currentDescribeBlock.beforeEachFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
SimpleMocha.prototype.afterEach = function( fn ){ |
|||
this.currentDescribeBlock.afterEachFn = mkAsyncFn( fn ); |
|||
}; |
|||
|
|||
|
|||
module.exports = SimpleMocha; |
@ -0,0 +1,57 @@ |
|||
|
|||
|
|||
var pr = console.log; |
|||
|
|||
var INDENT = ' '; |
|||
var STATUS_FLAG = { |
|||
true : '\u001b[32m\u001b[1m' + '✔' + '\u001b[22m\u001b[39m', |
|||
false : '\u001b[31m\u001b[1m' + '✗' + '\u001b[22m\u001b[39m', |
|||
}; |
|||
|
|||
|
|||
|
|||
function getIndent( level ){ |
|||
return INDENT.repeat( level ); |
|||
} |
|||
|
|||
|
|||
function print( level, item ){ |
|||
var indent = getIndent( level ); |
|||
var status = STATUS_FLAG[ item.isSuccess ]; |
|||
var timeTaken = '(' + ( item.endTime - item.startTime ) + 'ms)'; |
|||
pr( [ indent, status, item.description, timeTaken ].join(' ') ); |
|||
}; |
|||
|
|||
|
|||
function safeFn( fn ){ |
|||
return function( done ){ |
|||
try{ |
|||
fn( done ) |
|||
} catch( e ){ |
|||
done( e ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
function mkAsyncFn( fn ){ |
|||
if( fn.length ){ |
|||
return safeFn( fn ); |
|||
} |
|||
return safeFn( function( done ){ |
|||
setTimeout( function(){ |
|||
fn(); |
|||
done(); |
|||
}, 1 ); |
|||
}); |
|||
} |
|||
|
|||
|
|||
|
|||
module.exports = { |
|||
mkAsyncFn: mkAsyncFn, |
|||
print: print, |
|||
pr: pr, |
|||
getIndent: getIndent, |
|||
} |
Loading…
Reference in new issue