/*! * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('../util'), eql = require('../eql'); module.exports = function(should, Assertion) { var i = should.format; Assertion.add('match', function(other, description) { this.params = { operator: 'to match ' + i(other), message: description }; if(!eql(this.obj, other)) { if(util.isRegExp(other)) { // something - regex if(util.isString(this.obj)) { this.assert(other.exec(this.obj)); } else if(Array.isArray(this.obj)) { this.obj.forEach(function(item) { this.assert(other.exec(item));// should we try to convert to String and exec? }, this); } else if(util.isObject(this.obj)) { var notMatchedProps = [], matchedProps = []; util.forOwn(this.obj, function(value, name) { if(other.exec(value)) matchedProps.push(i(name)); else notMatchedProps.push(i(name)); }, this); if(notMatchedProps.length) this.params.operator += '\n\tnot matched properties: ' + notMatchedProps.join(', '); if(matchedProps.length) this.params.operator += '\n\tmatched properties: ' + matchedProps.join(', '); this.assert(notMatchedProps.length == 0); } // should we try to convert to String and exec? } else if(util.isFunction(other)) { var res; try { res = other(this.obj); } catch(e) { if(e instanceof should.AssertionError) { this.params.operator += '\n\t' + e.message; } throw e; } if(res instanceof Assertion) { this.params.operator += '\n\t' + res.getMessage(); } //if we throw exception ok - it is used .should inside if(util.isBoolean(res)) { this.assert(res); // if it is just boolean function assert on it } } else if(util.isObject(other)) { // try to match properties (for Object and Array) notMatchedProps = []; matchedProps = []; util.forOwn(other, function(value, key) { try { this.obj[key].should.match(value); matchedProps.push(key); } catch(e) { if(e instanceof should.AssertionError) { notMatchedProps.push(key); } else { throw e; } } }, this); if(notMatchedProps.length) this.params.operator += '\n\tnot matched properties: ' + notMatchedProps.join(', '); if(matchedProps.length) this.params.operator += '\n\tmatched properties: ' + matchedProps.join(', '); this.assert(notMatchedProps.length == 0); } else { this.assert(false); } } }); Assertion.add('matchEach', function(other, description) { this.params = { operator: 'to match each ' + i(other), message: description }; var f = other; if(util.isRegExp(other)) f = function(it) { return !!other.exec(it); }; else if(!util.isFunction(other)) f = function(it) { return eql(it, other); }; util.forOwn(this.obj, function(value, key) { var res = f(value, key); //if we throw exception ok - it is used .should inside if(util.isBoolean(res)) { this.assert(res); // if it is just boolean function assert on it } }, this); }); };