Files
hudozka/node_modules/should/lib/should.js
T
2014-02-12 12:36:59 +04:00

170 lines
3.4 KiB
JavaScript

/*!
* Should
* Copyright(c) 2010-2014 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
var util = require('./util')
, AssertionError = util.AssertionError
, inspect = util.inspect;
/**
* Our function should
* @param obj
* @returns {Assertion}
*/
var should = function(obj) {
return new Assertion(util.isWrapperType(obj) ? obj.valueOf(): obj);
};
/**
* Initialize a new `Assertion` with the given _obj_.
*
* @param {*} obj
* @api private
*/
var Assertion = should.Assertion = function Assertion(obj) {
this.obj = obj;
};
/**
Way to extend Assertion function. It uses some logic
to define only positive assertions and itself rule with negative assertion.
All actions happen in subcontext and this method take care about negation.
Potentially we can add some more modifiers that does not depends from state of assertion.
*/
Assertion.add = function(name, f, isGetter) {
var prop = {};
prop[isGetter ? 'get' : 'value'] = function() {
var context = new Assertion(this.obj);
context.copy = context.copyIfMissing;
try {
f.apply(context, arguments);
} catch(e) {
//copy data from sub context to this
this.copy(context);
//check for fail
if(e instanceof should.AssertionError) {
//negative fail
if(this.negate) {
this.obj = context.obj;
this.negate = false;
return this;
}
this.assert(false);
}
// throw if it is another exception
throw e;
}
//copy data from sub context to this
this.copy(context);
if(this.negate) {
this.assert(false);
}
this.obj = context.obj;
this.negate = false;
return this;
};
Object.defineProperty(Assertion.prototype, name, prop);
};
Assertion.alias = function(from, to) {
Assertion.prototype[to] = Assertion.prototype[from]
};
should.AssertionError = AssertionError;
var i = should.format = function i(value) {
if(util.isDate(value) && typeof value.inspect !== 'function') return value.toISOString(); //show millis in dates
return inspect(value, { depth: null });
};
should.use = function(f) {
f(this, Assertion);
return this;
};
/**
* Expose should to external world.
*/
exports = module.exports = should;
/**
* Expose api via `Object#should`.
*
* @api public
*/
Object.defineProperty(Object.prototype, 'should', {
set: function(){},
get: function(){
return should(this);
},
configurable: true
});
Assertion.prototype = {
constructor: Assertion,
assert: function(expr) {
if(expr) return;
var params = this.params;
var msg = params.message, generatedMessage = false;
if(!msg) {
msg = this.getMessage();
generatedMessage = true;
}
var err = new AssertionError({
message: msg
, actual: this.obj
, expected: params.expected
, stackStartFunction: this.assert
});
err.showDiff = params.showDiff;
err.operator = params.operator;
err.generatedMessage = generatedMessage;
throw err;
},
getMessage: function() {
return 'expected ' + i(this.obj) + (this.negate ? ' not ': ' ') +
this.params.operator + ('expected' in this.params ? ' ' + i(this.params.expected) : '');
},
copy: function(other) {
this.params = other.params;
},
copyIfMissing: function(other) {
if(!this.params) this.params = other.params;
},
/**
* Negation modifier.
*
* @api public
*/
get not() {
this.negate = !this.negate;
return this;
}
};