Comparing version 0.4.1 to 0.5.0
112
Gruntfile.js
'use strict'; | ||
var config = { | ||
targets: { | ||
test: ['test/**/*.js'], | ||
src: ['lib/**/*.js', '*.js'] | ||
}, | ||
timeout: 5000 | ||
targets: { | ||
test: ['test/**/*.js'], | ||
src: ['lib/**/*.js', '*.js'] | ||
}, | ||
timeout: 5000 | ||
}; | ||
@@ -12,55 +12,55 @@ config.targets.all = config.targets.test.concat(config.targets.src); | ||
module.exports = function(grunt) { | ||
grunt.initConfig({ | ||
mochaTest: { | ||
test: { | ||
options: { | ||
reporter: 'spec', | ||
timeout: config.timeout | ||
}, | ||
src: config.targets.test | ||
} | ||
}, | ||
/* jshint camelcase:false */ | ||
mocha_istanbul: { | ||
test: { | ||
options: { | ||
// reporter: 'mocha-jenkins-reporter', | ||
coverageFolder: 'reports', | ||
timeout: config.timeout, | ||
reportFormats: ['cobertura', 'lcov', 'html'] | ||
}, | ||
src: config.targets.test | ||
} | ||
}, | ||
jshint: { | ||
options: { | ||
jshintrc: '.jshintrc' | ||
}, | ||
stdout: { | ||
src: config.targets.all, | ||
}, | ||
checkstyle: { | ||
src: config.targets.all, | ||
options: { | ||
reporter: 'checkstyle', | ||
reporterOutput: 'reports/jshint-checkstyle-result.xml' | ||
} | ||
} | ||
}, | ||
watch: { | ||
files: config.targets.all, | ||
tasks: ['default'] | ||
} | ||
}); | ||
grunt.initConfig({ | ||
mochaTest: { | ||
test: { | ||
options: { | ||
reporter: 'spec', | ||
timeout: config.timeout | ||
}, | ||
src: config.targets.test | ||
} | ||
}, | ||
/* jshint camelcase:false */ | ||
mocha_istanbul: { | ||
test: { | ||
options: { | ||
// reporter: 'mocha-jenkins-reporter', | ||
coverageFolder: 'reports', | ||
timeout: config.timeout, | ||
reportFormats: ['cobertura', 'lcov', 'html'] | ||
}, | ||
src: config.targets.test | ||
} | ||
}, | ||
jshint: { | ||
options: { | ||
jshintrc: '.jshintrc' | ||
}, | ||
stdout: { | ||
src: config.targets.all, | ||
}, | ||
checkstyle: { | ||
src: config.targets.all, | ||
options: { | ||
reporter: 'checkstyle', | ||
reporterOutput: 'reports/jshint-checkstyle-result.xml' | ||
} | ||
} | ||
}, | ||
watch: { | ||
files: config.targets.all, | ||
tasks: ['default'] | ||
} | ||
}); | ||
grunt.loadNpmTasks('grunt-mocha-test'); | ||
grunt.loadNpmTasks('grunt-mocha-istanbul'); | ||
grunt.loadNpmTasks('grunt-contrib-jshint'); | ||
grunt.loadNpmTasks('grunt-contrib-watch'); | ||
grunt.loadNpmTasks('grunt-notify'); | ||
grunt.loadNpmTasks('grunt-mocha-test'); | ||
grunt.loadNpmTasks('grunt-mocha-istanbul'); | ||
grunt.loadNpmTasks('grunt-contrib-jshint'); | ||
grunt.loadNpmTasks('grunt-contrib-watch'); | ||
grunt.loadNpmTasks('grunt-notify'); | ||
// Default task. | ||
grunt.registerTask('default', ['jshint:stdout', 'mochaTest']); | ||
grunt.registerTask('test', ['default']); | ||
grunt.registerTask('coverage', ['mocha_istanbul']); | ||
// Default task. | ||
grunt.registerTask('default', ['jshint:stdout', 'mochaTest']); | ||
grunt.registerTask('test', ['default']); | ||
grunt.registerTask('coverage', ['mocha_istanbul']); | ||
}; |
@@ -32,2 +32,3 @@ /* | ||
var utils = require('./utils'); | ||
_.mixin(utils.mixins); | ||
var events = require('events'); | ||
@@ -37,409 +38,444 @@ var PREFIX = 'deride'; | ||
function Expectations(obj, method) { | ||
var debug = require('debug')(PREFIX + ':expectations:' + method); | ||
var timesCalled = 0; | ||
var calledWithArgs = {}; | ||
var debug = require('debug')(PREFIX + ':expectations:' + method); | ||
var timesCalled = 0; | ||
var calledWithArgs = {}; | ||
function checkArg(expected, values) { | ||
if (_.isObject(expected)) { | ||
return _.some(_.filter(values, expected)); | ||
} | ||
return _.includes(values, expected); | ||
} | ||
function checkArg(expected, values) { | ||
if (_.isObject(expected)) { | ||
return _.some(_.filter(values, expected)); | ||
} | ||
return _.includes(values, expected); | ||
} | ||
function checkArgs(expectedArgs, callArgs, evaluator) { | ||
var values = _.values(callArgs); | ||
var argResults = []; | ||
for (var argIndex = 0; argIndex < expectedArgs.length; argIndex++) { | ||
var expected = expectedArgs[argIndex]; | ||
debug('expected', expected, 'in', values); | ||
var foundArg = checkArg(expected, values); | ||
argResults.push(foundArg); | ||
} | ||
return evaluator(argResults); | ||
} | ||
function checkArgs(expectedArgs, callArgs, evaluator) { | ||
var values = _.values(callArgs); | ||
var argResults = []; | ||
for (var argIndex = 0; argIndex < expectedArgs.length; argIndex++) { | ||
var expected = expectedArgs[argIndex]; | ||
debug('expected', expected, 'in', values); | ||
var foundArg = checkArg(expected, values); | ||
argResults.push(foundArg); | ||
} | ||
return evaluator(argResults); | ||
} | ||
function checkAnyArgs(expectedArgs, callArgs) { | ||
return checkArgs(expectedArgs, callArgs, _.some); | ||
} | ||
function checkAnyArgs(expectedArgs, callArgs) { | ||
return checkArgs(expectedArgs, callArgs, _.some); | ||
} | ||
function withArgs() { | ||
var args = _.values(arguments); | ||
assertArgsWithEvaluator(calledWithArgs, args, _.every); | ||
return self.called; | ||
} | ||
function withArgs() { | ||
var args = _.values(arguments); | ||
assertArgsWithEvaluator(calledWithArgs, args, _.every); | ||
} | ||
function withSingleArg(arg) { | ||
var args = [arg]; | ||
assertArgsWithEvaluator(calledWithArgs, args, _.some); | ||
return self.called; | ||
} | ||
function withSingleArg(arg) { | ||
var args = [arg]; | ||
assertArgsWithEvaluator(calledWithArgs, args, _.some); | ||
} | ||
function assertArgsWithEvaluator(argsToCheck, args, evaluator) { | ||
var callResults = []; | ||
_.forEach(argsToCheck, function(value) { | ||
debug('checking', value, args); | ||
var argResult = checkArgs(args, value, evaluator); | ||
callResults.push(argResult); | ||
function withMatch(pattern) { | ||
debug(calledWithArgs); | ||
var matched = false; | ||
_.forEach(calledWithArgs, function(args) { | ||
if (matched) { | ||
return; | ||
} | ||
_.forEach(_.values(args), function(arg) { | ||
if (matched) { | ||
return; | ||
} | ||
if (_.isObject(arg)) { | ||
matched = objectPatternMatchProperties(arg, pattern); | ||
debug('is object match?', matched, arg, pattern); | ||
return; | ||
} | ||
matched = pattern.test(arg); | ||
debug('is match?', matched, arg, pattern); | ||
}); | ||
}); | ||
if (!matched) { | ||
assert.fail(calledWithArgs, pattern, 'Expected ' + method + ' to be called matching: ' + pattern); | ||
} | ||
} | ||
function objectPatternMatchProperties(obj, pattern) { | ||
var matched = false; | ||
_.deepMapValues(obj, function (i) { | ||
if (!matched) { | ||
matched = pattern.test(i); | ||
} | ||
debug(i, matched); | ||
}); | ||
var result = _.some(callResults); | ||
assert(result, 'Expected ' + method + ' to be called with: ' + args.join(', ')); | ||
} | ||
return matched; | ||
} | ||
function withArg(args) { | ||
return function(arg) { | ||
assert(checkAnyArgs([arg], args)); | ||
}; | ||
} | ||
function assertArgsWithEvaluator(argsToCheck, args, evaluator) { | ||
var callResults = []; | ||
_.forEach(argsToCheck, function(value) { | ||
debug('checking', value, args); | ||
var argResult = checkArgs(args, value, evaluator); | ||
callResults.push(argResult); | ||
}); | ||
var result = _.some(callResults); | ||
assert(result, 'Expected ' + method + ' to be called with: ' + args.join(', ')); | ||
} | ||
function invocation(index) { | ||
if (!(index.toString() in calledWithArgs)) { | ||
throw new Error('invocation out of range'); | ||
} | ||
var arg = calledWithArgs[index.toString()]; | ||
return { | ||
withArg: withArg(arg) | ||
}; | ||
} | ||
function withArg(args) { | ||
return function(arg) { | ||
assert(checkAnyArgs([arg], args)); | ||
}; | ||
} | ||
function times(number, err) { | ||
if (!err) { | ||
err = 'Expected ' + method + ' to be called ' + utils.humanise(number) + ' but was ' + timesCalled; | ||
} | ||
assert.equal(timesCalled, number, err); | ||
} | ||
function invocation(index) { | ||
if (!(index.toString() in calledWithArgs)) { | ||
throw new Error('invocation out of range'); | ||
} | ||
var arg = calledWithArgs[index.toString()]; | ||
return { | ||
withArg: withArg(arg) | ||
}; | ||
} | ||
function calledLteGte(number, predicate, friendly, err) { | ||
if (!err) { | ||
err = 'Expected ' + method + ' to be called ' + friendly + ' ' + utils.humanise(number) + ' but was ' + timesCalled; | ||
} | ||
assert.ok(predicate(timesCalled, number), err); | ||
} | ||
function times(number, err) { | ||
if (!err) { | ||
err = 'Expected ' + method + ' to be called ' + utils.humanise(number) + ' but was ' + timesCalled; | ||
} | ||
assert.equal(timesCalled, number, err); | ||
} | ||
function calledLt(number, err) { | ||
calledLteGte(number, _.lt, 'less than', err); | ||
} | ||
function calledLteGte(number, predicate, friendly, err) { | ||
if (!err) { | ||
err = 'Expected ' + method + ' to be called ' + friendly + ' ' + utils.humanise(number) + ' but was ' + timesCalled; | ||
} | ||
assert.ok(predicate(timesCalled, number), err); | ||
} | ||
function calledLte(number, err) { | ||
calledLteGte(number, _.lte, 'less than or equal to', err); | ||
} | ||
function calledLt(number, err) { | ||
calledLteGte(number, _.lt, 'less than', err); | ||
} | ||
function calledGt(number, err) { | ||
calledLteGte(number, _.gt, 'greater than', err); | ||
} | ||
function calledLte(number, err) { | ||
calledLteGte(number, _.lte, 'less than or equal to', err); | ||
} | ||
function calledGte(number, err) { | ||
calledLteGte(number, _.gte, 'greater than or equal to', err); | ||
} | ||
function calledGt(number, err) { | ||
calledLteGte(number, _.gt, 'greater than', err); | ||
} | ||
function never(err) { | ||
times(0, err); | ||
} | ||
function calledGte(number, err) { | ||
calledLteGte(number, _.gte, 'greater than or equal to', err); | ||
} | ||
function calledOnce(err) { | ||
times(1, err); | ||
} | ||
function never(err) { | ||
times(0, err); | ||
} | ||
function calledTwice(err) { | ||
times(2, err); | ||
} | ||
function calledOnce(err) { | ||
times(1, err); | ||
} | ||
function reset() { | ||
timesCalled = 0; | ||
calledWithArgs = {}; | ||
} | ||
function calledTwice(err) { | ||
times(2, err); | ||
} | ||
function call() { | ||
calledWithArgs[timesCalled++] = arguments; | ||
} | ||
function reset() { | ||
timesCalled = 0; | ||
calledWithArgs = {}; | ||
} | ||
function negate(func) { | ||
return function() { | ||
var args = _.values(arguments); | ||
try { | ||
func.call(null, args); | ||
} catch (err) { | ||
return self; | ||
} | ||
assert(false); | ||
}; | ||
} | ||
function call() { | ||
calledWithArgs[timesCalled++] = arguments; | ||
} | ||
function addNotMethods(obj) { | ||
var methods = {}; | ||
var calledMethods = _.omit(utils.methods(obj.called), 'reset'); | ||
_.forEach(calledMethods, function(method) { | ||
methods[method] = negate(obj.called[method]); | ||
}); | ||
obj.called.not = methods; | ||
return obj; | ||
} | ||
function negate(func) { | ||
return function() { | ||
var args = _.values(arguments); | ||
try { | ||
func.call(null, args); | ||
} catch (err) { | ||
return self; | ||
} | ||
assert(false); | ||
}; | ||
} | ||
var self = { | ||
called: { | ||
times: times, | ||
never: never, | ||
once: calledOnce, | ||
twice: calledTwice, | ||
lt: calledLt, | ||
lte: calledLte, | ||
gt: calledGt, | ||
gte: calledGte, | ||
reset: reset, | ||
withArgs: withArgs, | ||
withArg: withSingleArg | ||
}, | ||
invocation: invocation, | ||
call: call | ||
}; | ||
function addNotMethods(obj) { | ||
var methods = {}; | ||
var calledMethods = _.omit(utils.methods(obj.called), 'reset'); | ||
_.forEach(calledMethods, function(method) { | ||
methods[method] = negate(obj.called[method]); | ||
}); | ||
obj.called.not = methods; | ||
return obj; | ||
} | ||
return (function() { | ||
return Object.freeze(addNotMethods(self)); | ||
}()); | ||
var self = { | ||
called: { | ||
times: times, | ||
never: never, | ||
once: calledOnce, | ||
twice: calledTwice, | ||
lt: calledLt, | ||
lte: calledLte, | ||
gt: calledGt, | ||
gte: calledGte, | ||
reset: reset, | ||
withArgs: withArgs, | ||
withArg: withSingleArg, | ||
withMatch: withMatch | ||
}, | ||
invocation: invocation, | ||
call: call | ||
}; | ||
return (function() { | ||
return Object.freeze(addNotMethods(self)); | ||
}()); | ||
} | ||
function Setup(obj, method, emitter) { | ||
var debug = require('debug')(PREFIX + ':setup:' + method); | ||
var Promises = require('when'); | ||
var originalMethod = obj[method]; | ||
var callToInvoke = normalCall; | ||
var callToInvokeOnArguments = {}; | ||
var argumentsPredicate; | ||
var callBasedOnPredicate; | ||
var predicate; | ||
var debug = require('debug')(PREFIX + ':setup:' + method); | ||
var Promises = require('when'); | ||
var originalMethod = obj[method]; | ||
var callToInvoke = normalCall; | ||
var callToInvokeOnArguments = {}; | ||
var argumentsPredicate; | ||
var callBasedOnPredicate; | ||
var predicate; | ||
function call() { | ||
var key = serializeArgs(arguments); | ||
var callBasedOnArgs = callToInvokeOnArguments[key]; | ||
if (callBasedOnArgs !== null && callBasedOnArgs !== undefined) { | ||
return callBasedOnArgs.apply(self, arguments); | ||
} else { | ||
if (_.isFunction(callBasedOnPredicate)) { | ||
return callBasedOnPredicate.apply(self, arguments); | ||
} | ||
return callToInvoke.apply(self, arguments); | ||
} | ||
} | ||
function call() { | ||
var key = serializeArgs(arguments); | ||
var callBasedOnArgs = callToInvokeOnArguments[key]; | ||
if (callBasedOnArgs !== null && callBasedOnArgs !== undefined) { | ||
return callBasedOnArgs.apply(self, arguments); | ||
} else { | ||
if (_.isFunction(callBasedOnPredicate)) { | ||
return callBasedOnPredicate.apply(self, arguments); | ||
} | ||
return callToInvoke.apply(self, arguments); | ||
} | ||
} | ||
function getArgArray(argArray) { | ||
if (argArray.length === 1 && _.isArray(argArray[0])) { | ||
return argArray[0]; | ||
} | ||
return argArray; | ||
} | ||
function getArgArray(argArray) { | ||
if (argArray.length === 1 && _.isArray(argArray[0])) { | ||
return argArray[0]; | ||
} | ||
return argArray; | ||
} | ||
function toCallbackWith() { | ||
var args = getArgArray([].slice.call(arguments)); | ||
var func = function() { | ||
debug('toCallbackWith', args); | ||
var index = _.findLastIndex(arguments, _.isFunction); | ||
arguments[index].apply(null, args); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toCallbackWith() { | ||
var args = getArgArray([].slice.call(arguments)); | ||
var func = function() { | ||
debug('toCallbackWith', args); | ||
var index = _.findLastIndex(arguments, _.isFunction); | ||
arguments[index].apply(null, args); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toDoThis(func) { | ||
var wrapper = function() { | ||
debug('toDoThis override'); | ||
var result = func.apply(obj, arguments); | ||
return result; | ||
}; | ||
checkArgumentsToInvoke(wrapper); | ||
} | ||
function toDoThis(func) { | ||
var wrapper = function() { | ||
debug('toDoThis override'); | ||
var result = func.apply(obj, arguments); | ||
return result; | ||
}; | ||
checkArgumentsToInvoke(wrapper); | ||
} | ||
function toEmit() { | ||
var args = Array.prototype.slice.call(arguments); | ||
var func = function() { | ||
emitter.emit.apply(emitter, args); | ||
return originalMethod.apply(obj, arguments); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toEmit() { | ||
var args = Array.prototype.slice.call(arguments); | ||
var func = function() { | ||
emitter.emit.apply(emitter, args); | ||
return originalMethod.apply(obj, arguments); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toRejectWith(arg) { | ||
var func = function() { | ||
debug('toRejectWith'); | ||
return Promises.reject(arg); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toRejectWith(arg) { | ||
var func = function() { | ||
debug('toRejectWith'); | ||
return Promises.reject(arg); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toResolveWith(arg) { | ||
var func = function() { | ||
debug('toResolveWith'); | ||
return Promises.resolve(arg); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toResolveWith(arg) { | ||
var func = function() { | ||
debug('toResolveWith'); | ||
return Promises.resolve(arg); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toReturn(value) { | ||
var overrideReturnValue = function() { | ||
debug('toReturn', value); | ||
return value; | ||
}; | ||
checkArgumentsToInvoke(overrideReturnValue); | ||
} | ||
function toReturn(value) { | ||
var overrideReturnValue = function() { | ||
debug('toReturn', value); | ||
return value; | ||
}; | ||
checkArgumentsToInvoke(overrideReturnValue); | ||
} | ||
function toThrow(message) { | ||
var func = function() { | ||
debug('toThrow', message); | ||
throw new Error(message); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toThrow(message) { | ||
var func = function() { | ||
debug('toThrow', message); | ||
throw new Error(message); | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toTimeWarp(milliseconds) { | ||
var func = function() { | ||
debug('toTimeWarp', milliseconds); | ||
var originalTimeoutFunc = setTimeout; | ||
setTimeout = function(delegate, timeout) { | ||
originalTimeoutFunc(delegate, timeout - milliseconds); | ||
}; | ||
var result = originalMethod.apply(obj, arguments); | ||
return result; | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function toTimeWarp(milliseconds) { | ||
var func = function() { | ||
debug('toTimeWarp', milliseconds); | ||
var originalTimeoutFunc = setTimeout; | ||
setTimeout = function(delegate, timeout) { | ||
originalTimeoutFunc(delegate, timeout - milliseconds); | ||
}; | ||
var result = originalMethod.apply(obj, arguments); | ||
return result; | ||
}; | ||
checkArgumentsToInvoke(func); | ||
} | ||
function when() { | ||
if (_.isFunction(arguments['0'])) { | ||
predicate = arguments['0']; | ||
} else { | ||
argumentsPredicate = arguments; | ||
} | ||
return Object.freeze(self); | ||
} | ||
function when() { | ||
if (_.isFunction(arguments['0'])) { | ||
predicate = arguments['0']; | ||
} else { | ||
argumentsPredicate = arguments; | ||
} | ||
return Object.freeze(self); | ||
} | ||
function checkArgumentsToInvoke(func) { | ||
if (argumentsPredicate !== undefined) { | ||
var key = serializeArgs(argumentsPredicate); | ||
callToInvokeOnArguments[key] = func; | ||
} else { | ||
if (_.isFunction(predicate)) { | ||
callBasedOnPredicate = function() { | ||
debug('check predicate'); | ||
if (predicate.apply(self, arguments)) { | ||
debug('predicate true'); | ||
return func.apply(self, arguments); | ||
} else { | ||
debug('predicate false'); | ||
return callToInvoke.apply(self, arguments); | ||
} | ||
}; | ||
} else { | ||
callToInvoke = func; | ||
} | ||
} | ||
argumentsPredicate = undefined; | ||
} | ||
function checkArgumentsToInvoke(func) { | ||
if (argumentsPredicate !== undefined) { | ||
var key = serializeArgs(argumentsPredicate); | ||
callToInvokeOnArguments[key] = func; | ||
} else { | ||
if (_.isFunction(predicate)) { | ||
callBasedOnPredicate = function() { | ||
debug('check predicate'); | ||
if (predicate.apply(self, arguments)) { | ||
debug('predicate true'); | ||
return func.apply(self, arguments); | ||
} else { | ||
debug('predicate false'); | ||
return callToInvoke.apply(self, arguments); | ||
} | ||
}; | ||
} else { | ||
callToInvoke = func; | ||
} | ||
} | ||
argumentsPredicate = undefined; | ||
} | ||
function normalCall() { | ||
debug('normal call', method); | ||
var result = originalMethod.apply(obj, arguments); | ||
return result; | ||
} | ||
function normalCall() { | ||
debug('normal call', method); | ||
var result = originalMethod.apply(obj, arguments); | ||
return result; | ||
} | ||
function serializeArgs(args) { | ||
return JSON.stringify(args); | ||
} | ||
function serializeArgs(args) { | ||
return JSON.stringify(args); | ||
} | ||
var self = { | ||
toDoThis: toDoThis, | ||
toReturn: toReturn, | ||
toThrow: toThrow, | ||
toCallbackWith: toCallbackWith, | ||
toResolveWith: toResolveWith, | ||
toRejectWith: toRejectWith, | ||
toTimeWarp: toTimeWarp, | ||
toEmit: toEmit, | ||
when: when, | ||
call: call | ||
}; | ||
var self = { | ||
toDoThis: toDoThis, | ||
toReturn: toReturn, | ||
toThrow: toThrow, | ||
toCallbackWith: toCallbackWith, | ||
toResolveWith: toResolveWith, | ||
toRejectWith: toRejectWith, | ||
toTimeWarp: toTimeWarp, | ||
toEmit: toEmit, | ||
when: when, | ||
call: call | ||
}; | ||
return (function() { | ||
return Object.freeze(self); | ||
}()); | ||
return (function() { | ||
return Object.freeze(self); | ||
}()); | ||
} | ||
function wrap(obj) { | ||
var debug = require('debug')(PREFIX + ':wrap'); | ||
var objMethods = utils.methods(obj); | ||
var self = {}; | ||
var expectMethods = {}; | ||
var setupMethods = {}; | ||
var eventEmitter = new events.EventEmitter(); | ||
utils.proxyFunctions(self, eventEmitter, ['on', 'once', 'emit']); | ||
var debug = require('debug')(PREFIX + ':wrap'); | ||
var objMethods = utils.methods(obj); | ||
var self = {}; | ||
var expectMethods = {}; | ||
var setupMethods = {}; | ||
var eventEmitter = new events.EventEmitter(); | ||
utils.proxyFunctions(self, eventEmitter, ['on', 'once', 'emit']); | ||
function setupForMethod(method) { | ||
debug(method); | ||
return function() { | ||
expectMethods[method].call.apply(obj, arguments); | ||
return setupMethods[method].call.apply(obj, arguments); | ||
}; | ||
} | ||
function setupForMethod(method) { | ||
debug(method); | ||
return function() { | ||
expectMethods[method].call.apply(obj, arguments); | ||
return setupMethods[method].call.apply(obj, arguments); | ||
}; | ||
} | ||
for (var i = 0; i < objMethods.length; i++) { | ||
var method = objMethods[i]; | ||
expectMethods[method] = new Expectations(obj, method); | ||
setupMethods[method] = new Setup(obj, method, eventEmitter); | ||
self[method] = setupForMethod(method); | ||
} | ||
for (var i = 0; i < objMethods.length; i++) { | ||
var method = objMethods[i]; | ||
expectMethods[method] = new Expectations(obj, method); | ||
setupMethods[method] = new Setup(obj, method, eventEmitter); | ||
self[method] = setupForMethod(method); | ||
} | ||
self.expect = expectMethods; | ||
self.called = { | ||
reset: function() { | ||
_.forEach(expectMethods, function(method) { | ||
method.called.reset(); | ||
}); | ||
} | ||
}; | ||
self.setup = setupMethods; | ||
return Object.freeze(_.merge({}, obj, self)); | ||
self.expect = expectMethods; | ||
self.called = { | ||
reset: function() { | ||
_.forEach(expectMethods, function(method) { | ||
method.called.reset(); | ||
}); | ||
} | ||
}; | ||
self.setup = setupMethods; | ||
return Object.freeze(_.merge({}, obj, self)); | ||
} | ||
function func() { | ||
var debug = require('debug')(PREFIX + ':func'); | ||
var objHarness = { | ||
value: function() {} | ||
}; | ||
var wrapped = wrap(objHarness); | ||
var debug = require('debug')(PREFIX + ':func'); | ||
var objHarness = { | ||
value: function() {} | ||
}; | ||
var wrapped = wrap(objHarness); | ||
function createFunc() { | ||
debug('harness'); | ||
var returnVal = wrapped.value.apply(objHarness, arguments); | ||
return returnVal; | ||
} | ||
createFunc.expect = wrapped.expect.value; | ||
createFunc.setup = wrapped.setup.value; | ||
function createFunc() { | ||
debug('harness'); | ||
var returnVal = wrapped.value.apply(objHarness, arguments); | ||
return returnVal; | ||
} | ||
createFunc.expect = wrapped.expect.value; | ||
createFunc.setup = wrapped.setup.value; | ||
return Object.freeze(createFunc); | ||
return Object.freeze(createFunc); | ||
} | ||
function stub(target, properties) { | ||
var debug = require('debug')(PREFIX + ':stub'); | ||
debug(target); | ||
var methods = []; | ||
if (_.isArray(target)) { | ||
methods = target; | ||
} else { | ||
methods = utils.methods(target); | ||
} | ||
var debug = require('debug')(PREFIX + ':stub'); | ||
debug(target); | ||
var methods = []; | ||
if (_.isArray(target)) { | ||
methods = target; | ||
} else { | ||
methods = utils.methods(target); | ||
} | ||
var stubObj = {}; | ||
var emptyMethod = function() { | ||
return function() {}; | ||
}; | ||
for (var i = 0; i < methods.length; i++) { | ||
stubObj[methods[i]] = emptyMethod(); | ||
} | ||
_.forEach(properties, function(prop) { | ||
Object.defineProperty(stubObj, prop.name, prop.options); | ||
}); | ||
return wrap(stubObj); | ||
var stubObj = {}; | ||
var emptyMethod = function() { | ||
return function() {}; | ||
}; | ||
for (var i = 0; i < methods.length; i++) { | ||
stubObj[methods[i]] = emptyMethod(); | ||
} | ||
_.forEach(properties, function(prop) { | ||
Object.defineProperty(stubObj, prop.name, prop.options); | ||
}); | ||
return wrap(stubObj); | ||
} | ||
module.exports = { | ||
wrap: wrap, | ||
stub: stub, | ||
func: func | ||
wrap: wrap, | ||
stub: stub, | ||
func: func | ||
}; |
@@ -17,3 +17,3 @@ 'use strict'; | ||
function methods(obj) { | ||
return _.functionsIn(obj); | ||
return _.functionsIn(obj); | ||
} | ||
@@ -32,6 +32,90 @@ | ||
var mixins = { | ||
deepMapValues: function(object, callback, propertyPath) { | ||
var properties = getProperties(propertyPath); | ||
if (_.isArray(object)) { | ||
return _.map(object, deepMapValuesIteratee); | ||
} else if (_.isObject(object) && !_.isDate(object) && !_.isRegExp(object)) { | ||
return _.extend({}, object, _.mapValues(object, deepMapValuesIteratee)); | ||
} else { | ||
return callback(object, properties); | ||
} | ||
function deepMapValuesIteratee(value, key) { | ||
return _.deepMapValues(value, callback, _.flatten([properties, key])); | ||
} | ||
function getProperties(propertyPath) { | ||
if (_.isArray(propertyPath)) { | ||
return propertyPath; | ||
} | ||
if (!_.isString(propertyPath)) { | ||
return []; | ||
} | ||
return parseStringPropertyPath(propertyPath); | ||
} | ||
function parseStringPropertyPath(propertyPath) { | ||
//jshint maxcomplexity:13 | ||
//jshint maxdepth:3 | ||
//REASON: taken from https://github.com/marklagendijk/lodash-deep/blob/master/lodash-deep.js | ||
// Need to look at refactoring it. | ||
var character = ''; | ||
var parsedPropertyPath = []; | ||
var parsedPropertyPathPart = ''; | ||
var escapeNextCharacter = false; | ||
var isSpecialCharacter = false; | ||
var insideBrackets = false; | ||
// Walk through the path and find backslashes that escape periods or other backslashes, and split on unescaped | ||
// periods and brackets. | ||
for (var i = 0; i < propertyPath.length; i++) { | ||
character = propertyPath[i]; | ||
isSpecialCharacter = (character === '\\' || character === '[' || character === ']' || character === '.'); | ||
if (isSpecialCharacter && !escapeNextCharacter) { | ||
if (insideBrackets && character !== ']') { | ||
throw new SyntaxError('unexpected "' + character + '" within brackets at character ' + i + ' in property path ' + propertyPath); | ||
} | ||
switch (character) { | ||
case '\\': | ||
escapeNextCharacter = true; | ||
break; | ||
case ']': | ||
insideBrackets = false; | ||
break; | ||
case '[': | ||
insideBrackets = true; | ||
/* falls through */ | ||
case '.': | ||
parsedPropertyPath.push(parsedPropertyPathPart); | ||
parsedPropertyPathPart = ''; | ||
break; | ||
} | ||
} else { | ||
parsedPropertyPathPart += character; | ||
escapeNextCharacter = false; | ||
} | ||
} | ||
if (parsedPropertyPath[0] === '') { | ||
//allow '[0]', or '.0' | ||
parsedPropertyPath.splice(0, 1); | ||
} | ||
// capture the final part | ||
parsedPropertyPath.push(parsedPropertyPathPart); | ||
return parsedPropertyPath; | ||
} | ||
} | ||
}; | ||
module.exports = { | ||
proxyFunctions: proxyFunctions, | ||
methods: methods, | ||
humanise: humanise | ||
humanise: humanise, | ||
mixins: mixins | ||
}; |
{ | ||
"name": "deride", | ||
"description": "Mocking library based on composition", | ||
"version": "0.4.1", | ||
"version": "0.5.0", | ||
"homepage": "https://github.com/guzzlerio/deride", | ||
@@ -6,0 +6,0 @@ "author": { |
@@ -41,2 +41,3 @@ # deride [![Build Status](https://travis-ci.org/guzzlerio/deride.svg?branch=master)](https://travis-ci.org/guzzlerio/deride) [![NPM version](https://badge.fury.io/js/deride.svg)](http://badge.fury.io/js/deride) [![Dependency Status](https://david-dm.org/guzzlerio/deride.svg)](https://david-dm.org/guzzlerio/deride) [![Stories in Ready](https://badge.waffle.io/guzzlerio/deride.png?label=ready&title=Ready)](https://waffle.io/guzzlerio/deride) [![Stories In Progress](https://badge.waffle.io/guzzlerio/deride.png?label=in%20progress&title=In%20Progres)](https://waffle.io/guzzlerio/deride) | ||
- [```obj```.expect.```method```.called.withArgs(args)](#called-withargs) | ||
- [```obj```.expect.```method```.called.withMatch(pattern)](#called-withmatch) | ||
@@ -503,2 +504,27 @@ **All of the above can be negated e.g. negating the `.withArgs` would be: ** | ||
<a name="called-withmatch" /> | ||
## Use a RexExp match for the assertion on any args being used in any invocation | ||
### when the arg is a primitive object | ||
```javascript | ||
var bob = deride.stub(['greet']); | ||
bob.greet('The inspiration for this was that my colleague was having a'); | ||
bob.greet({a: 123, b: 'talula'}, 123, 'something'); | ||
bob.expect.greet.called.withMatch(/^The inspiration for this was/); | ||
``` | ||
### when the arg is not a primitive object | ||
```javascript | ||
var bob = deride.stub(['greet']); | ||
bob.greet('The inspiration for this was that my colleague was having a'); | ||
bob.greet({a: 123, b: { a: {'talula'}}, 123, 'something'); | ||
bob.expect.greet.called.withMatch(/^talula/gi); | ||
``` | ||
--- | ||
## Contributing | ||
@@ -505,0 +531,0 @@ Please ensure that you run ```grunt```, have no style warnings and that all the tests are passing. |
@@ -130,2 +130,44 @@ /* | ||
}); | ||
it('allows matching call args with regex', function() { | ||
var bob = deride.stub(['greet']); | ||
bob.greet('The inspiration for this was that my colleague was having a'); | ||
bob.greet({ | ||
a: 123, | ||
b: 'talula' | ||
}, 123, 'something'); | ||
bob.expect.greet.called.withMatch(/^The inspiration for this was/); | ||
}); | ||
it('allows matching call args with regex', function() { | ||
var bob = deride.stub(['greet']); | ||
bob.greet('The inspiration for this was that my colleague was having a'); | ||
(function() { | ||
bob.expect.greet.called.withMatch(/^talula/); | ||
}).should.throw('Expected greet to be called matching: /^talula/'); | ||
}); | ||
it('allows matching call args with regex in objects', function() { | ||
var bob = deride.stub(['greet']); | ||
bob.greet('The inspiration for this was that my colleague was having a'); | ||
bob.greet({ | ||
a: 123, | ||
b: 'talula' | ||
}, 123, 'something'); | ||
bob.expect.greet.called.withMatch(/^talula/gi); | ||
}); | ||
it('allows matching call args with regex in deep objects', function() { | ||
var bob = deride.stub(['greet']); | ||
bob.greet('The inspiration for this was that my colleague was having a'); | ||
bob.greet({ | ||
a: 123, | ||
b: { a: 'talula' } | ||
}, 123, 'something'); | ||
bob.expect.greet.called.withMatch(/^talula/gi); | ||
}); | ||
}); | ||
@@ -158,3 +200,2 @@ | ||
myClass.expect.doStuff.called.reset(); | ||
/* jshint immed: false */ | ||
(function() { | ||
@@ -739,3 +780,2 @@ myClass.expect.doStuff.called.withArgs('test'); | ||
describe('providing a predicate to when', function() { | ||
describe('with a single argument', function() { | ||
@@ -742,0 +782,0 @@ function resourceMatchingPredicate(msg) { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
65023
1351
536