cloudboost-tv
Version:
Database Service that does Storage, Search, Real-time and a whole lot more.
165 lines (145 loc) • 5.91 kB
JavaScript
/*!
* Should
* Copyright(c) 2010-2014 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
var util = require('../util');
var eql = require('should-equal');
module.exports = function(should, Assertion) {
var i = should.format;
/**
* Asserts if given object match `other` object, using some assumptions:
* First object matched if they are equal,
* If `other` is a regexp and given object is a string check on matching with regexp
* If `other` is a regexp and given object is an array check if all elements matched regexp
* If `other` is a regexp and given object is an object check values on matching regexp
* If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
* If `other` is an object check if the same keys matched with above rules
* All other cases failed
*
* @name match
* @memberOf Assertion
* @category assertion matching
* @param {*} other Object to match
* @param {string} [description] Optional message
* @example
* 'foobar'.should.match(/^foo/);
* 'foobar'.should.not.match(/^bar/);
*
* ({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);
*
* ['a', 'b', 'c'].should.match(/[a-z]/);
*
* (5).should.not.match(function(n) {
* return n < 0;
* });
* (5).should.not.match(function(it) {
* it.should.be.an.Array;
* });
* ({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should
* .match({ a: 10, b: /c$/, c: function(it) {
* return it.should.have.property('d', 10);
* }});
*
* [10, 'abc', { d: 10 }, 0].should
* .match({ '0': 10, '1': /c$/, '2': function(it) {
* return it.should.have.property('d', 10);
* }});
*/
Assertion.add('match', function(other, description) {
this.params = {operator: 'to match ' + i(other), message: description};
if(!eql(this.obj, other).result) {
if(other instanceof RegExp) { // something - regex
if(typeof this.obj == 'string') {
this.assert(other.exec(this.obj));
} else if(util.isIndexable(this.obj)) {
util.forEach(this.obj, function(item) {
this.assert(other.exec(item));// should we try to convert to String and exec?
}, this);
} else if(null != this.obj && typeof this.obj == 'object') {
var notMatchedProps = [], matchedProps = [];
util.forEach(this.obj, function(value, name) {
if(other.exec(value)) matchedProps.push(util.formatProp(name));
else notMatchedProps.push(util.formatProp(name) + ' (' + i(value) + ')');
}, this);
if(notMatchedProps.length)
this.params.operator += '\n not matched properties: ' + notMatchedProps.join(', ');
if(matchedProps.length)
this.params.operator += '\n matched properties: ' + matchedProps.join(', ');
this.assert(notMatchedProps.length == 0);
} // should we try to convert to String and exec?
} else if(typeof other == 'function') {
var res;
res = other(this.obj);
//if(res instanceof Assertion) {
// this.params.operator += '\n ' + res.getMessage();
//}
//if we throw exception ok - it is used .should inside
if(typeof res == 'boolean') {
this.assert(res); // if it is just boolean function assert on it
}
} else if(other != null && typeof other == 'object') { // try to match properties (for Object and Array)
notMatchedProps = [];
matchedProps = [];
util.forEach(other, function(value, key) {
try {
should(this.obj[key]).match(value);
matchedProps.push(util.formatProp(key));
} catch(e) {
if(e instanceof should.AssertionError) {
notMatchedProps.push(util.formatProp(key) + ' (' + i(this.obj[key]) + ')');
} else {
throw e;
}
}
}, this);
if(notMatchedProps.length)
this.params.operator += '\n not matched properties: ' + notMatchedProps.join(', ');
if(matchedProps.length)
this.params.operator += '\n matched properties: ' + matchedProps.join(', ');
this.assert(notMatchedProps.length == 0);
} else {
this.assert(false);
}
}
});
/**
* Asserts if given object values or array elements all match `other` object, using some assumptions:
* First object matched if they are equal,
* If `other` is a regexp - matching with regexp
* If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
* All other cases check if this `other` equal to each element
*
* @name matchEach
* @memberOf Assertion
* @category assertion matching
* @param {*} other Object to match
* @param {string} [description] Optional message
* @example
* [ 'a', 'b', 'c'].should.matchEach(/\w+/);
* [ 'a', 'a', 'a'].should.matchEach('a');
*
* [ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') });
*
* { a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') });
*/
Assertion.add('matchEach', function(other, description) {
this.params = {operator: 'to match each ' + i(other), message: description};
var f = other;
if(other instanceof RegExp)
f = function(it) {
return !!other.exec(it);
};
else if(typeof other != 'function')
f = function(it) {
return eql(it, other).result;
};
util.forEach(this.obj, function(value, key) {
var res = f(value, key);
//if we throw exception ok - it is used .should inside
if(typeof res == 'boolean') {
this.assert(res); // if it is just boolean function assert on it
}
}, this);
});
};