Comparing version 1.0.0 to 1.1.0
88
index.js
@@ -1,62 +0,61 @@ | ||
'use strict'; | ||
'use strict' | ||
function isFunction(funktion) { | ||
return funktion && {}.toString.call(funktion) === '[object Function]'; | ||
function isFunction (funktion) { | ||
return funktion && {}.toString.call(funktion) === '[object Function]' | ||
} | ||
// Default to complaining loudly when things don't go according to plan. | ||
var logger = console.error.bind(console); | ||
var logger = console.error.bind(console) | ||
// Keep initialization idempotent. | ||
function shimmer(options) { | ||
function shimmer (options) { | ||
if (options && options.logger) { | ||
if (!isFunction(options.logger)) logger("new logger isn't a function, not replacing"); | ||
else logger = options.logger; | ||
if (!isFunction(options.logger)) logger("new logger isn't a function, not replacing") | ||
else logger = options.logger | ||
} | ||
} | ||
function wrap(nodule, name, wrapper) { | ||
function wrap (nodule, name, wrapper) { | ||
if (!nodule || !nodule[name]) { | ||
logger("no original function " + name + " to wrap"); | ||
return; | ||
logger('no original function ' + name + ' to wrap') | ||
return | ||
} | ||
if (!wrapper) { | ||
logger("no wrapper function"); | ||
logger((new Error()).stack); | ||
return; | ||
logger('no wrapper function') | ||
logger((new Error()).stack) | ||
return | ||
} | ||
if (!isFunction(nodule[name]) || !isFunction(wrapper)) { | ||
logger("original object and wrapper must be functions"); | ||
return; | ||
logger('original object and wrapper must be functions') | ||
return | ||
} | ||
var original = nodule[name] | ||
, wrapped = wrapper(original) | ||
; | ||
var wrapped = wrapper(original, name) | ||
wrapped.__original = original; | ||
wrapped.__original = original | ||
wrapped.__unwrap = function () { | ||
if (nodule[name] === wrapped) nodule[name] = original; | ||
}; | ||
wrapped.__wrapped = true; | ||
if (nodule[name] === wrapped) nodule[name] = original | ||
} | ||
wrapped.__wrapped = true | ||
nodule[name] = wrapped; | ||
nodule[name] = wrapped | ||
return wrapped; | ||
return wrapped | ||
} | ||
function massWrap(nodules, names, wrapper) { | ||
function massWrap (nodules, names, wrapper) { | ||
if (!nodules) { | ||
logger("must provide one or more modules to patch"); | ||
logger((new Error()).stack); | ||
return; | ||
logger('must provide one or more modules to patch') | ||
logger((new Error()).stack) | ||
return | ||
} else if (!Array.isArray(nodules)) { | ||
nodules = [nodules]; | ||
nodules = [nodules] | ||
} | ||
if (!(names && Array.isArray(names))) { | ||
logger("must provide one or more functions to wrap on modules"); | ||
return; | ||
logger('must provide one or more functions to wrap on modules') | ||
return | ||
} | ||
@@ -66,26 +65,25 @@ | ||
names.forEach(function (name) { | ||
wrap(nodule, name, wrapper); | ||
}); | ||
}); | ||
wrap(nodule, name, wrapper) | ||
}) | ||
}) | ||
} | ||
function unwrap(nodule, name) { | ||
function unwrap (nodule, name) { | ||
if (!nodule || !nodule[name]) { | ||
logger("no function to unwrap."); | ||
logger((new Error()).stack); | ||
return; | ||
logger('no function to unwrap.') | ||
logger((new Error()).stack) | ||
return | ||
} | ||
if (!nodule[name].__unwrap) { | ||
logger("no original to unwrap to -- has " + name + " already been unwrapped?"); | ||
logger('no original to unwrap to -- has ' + name + ' already been unwrapped?') | ||
} else { | ||
return nodule[name].__unwrap() | ||
} | ||
else { | ||
return nodule[name].__unwrap(); | ||
} | ||
} | ||
shimmer.wrap = wrap; | ||
shimmer.massWrap = massWrap; | ||
shimmer.unwrap = unwrap; | ||
shimmer.wrap = wrap | ||
shimmer.massWrap = massWrap | ||
shimmer.unwrap = unwrap | ||
module.exports = shimmer; | ||
module.exports = shimmer |
{ | ||
"name": "shimmer", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Safe(r) monkeypatching for JavaScript.", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "tap test/*.tap.js" | ||
"test": "standard && tap test/*.tap.js --coverage" | ||
}, | ||
@@ -22,7 +22,8 @@ "repository": { | ||
"author": "Forrest L Norvell <ogd@aoaioxxysz.net>", | ||
"license": "BSD", | ||
"license": "BSD-2-Clause", | ||
"devDependencies": { | ||
"tap": "~0.4.3", | ||
"sinon": "~1.7.2" | ||
"sinon": "^1.17.2", | ||
"standard": "^5.3.1", | ||
"tap": "^2.2.0" | ||
} | ||
} |
@@ -0,1 +1,4 @@ | ||
[![Build Status](https://travis-ci.org/othiym23/shimmer.svg)](https://travis-ci.org/othiym23/shimmer) | ||
[![Coverage Status](https://coveralls.io/repos/othiym23/shimmer/badge.svg?branch=master)](https://coveralls.io/r/othiym23/shimmer?branch=master) | ||
## Safer monkeypatching for Node.js | ||
@@ -72,15 +75,1 @@ | ||
function (but will log). | ||
#### shimmer.wrapEmitter(emitter, mark, prepare) | ||
Wrap an EventEmitter's event listeners. Each listener will be passed to | ||
`mark` when it is registered with `.addListener()` or `.on()`, and then | ||
each listener is passed to `prepare` to be wrapped before it's called | ||
by the `.emit()` call. `wrapListener` deals with the single listener | ||
vs array of listeners logic, and also ensures that edge cases like | ||
`.removeListener()` being called from within an `.emit()` for the same | ||
event type is handled properly. | ||
The wrapped EE can be restored to its pristine state by using | ||
emitter.__unwrap(), but this should only be used if you *really* know | ||
what you're doing. |
@@ -1,49 +0,48 @@ | ||
'use strict'; | ||
'use strict' | ||
var tap = require('tap') | ||
, test = tap.test | ||
, sinon = require('sinon') | ||
, shimmer = require('../index.js') | ||
; | ||
var tap = require('tap') | ||
var test = tap.test | ||
var sinon = require('sinon') | ||
var shimmer = require('../index.js') | ||
test("shimmer initialization", function (t) { | ||
t.plan(4); | ||
test('shimmer initialization', function (t) { | ||
t.plan(4) | ||
t.doesNotThrow(function () { shimmer(); }); | ||
t.doesNotThrow(function () { shimmer() }) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withArgs("no original function undefined to wrap") | ||
.once(); | ||
.create('logger') | ||
.withArgs('no original function undefined to wrap') | ||
.once() | ||
t.doesNotThrow(function () { | ||
shimmer({logger : mock}); | ||
}, "initializer doesn't throw"); | ||
shimmer({logger: mock}) | ||
}, "initializer doesn't throw") | ||
t.doesNotThrow(function () { | ||
shimmer.wrap(); | ||
}, "invoking the wrap method with no params doesn't throw"); | ||
shimmer.wrap() | ||
}, "invoking the wrap method with no params doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger method was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger method was called with the expected message') | ||
}) | ||
test("shimmer initialized with non-function logger", function (t) { | ||
t.plan(2); | ||
test('shimmer initialized with non-function logger', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withArgs("new logger isn't a function, not replacing") | ||
.once(); | ||
.create('logger') | ||
.withArgs("new logger isn't a function, not replacing") | ||
.once() | ||
shimmer({logger : mock}); | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer({logger : {ham : 'chunx'}}); | ||
}, "even bad initialization doesn't throw"); | ||
shimmer({logger: {ham: 'chunx'}}) | ||
}, "even bad initialization doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger initialization failed in the expected way"); | ||
}); | ||
mock.verify() | ||
}, 'logger initialization failed in the expected way') | ||
}) |
@@ -0,176 +1,174 @@ | ||
'use strict' | ||
'use strict'; | ||
var tap = require('tap') | ||
var test = tap.test | ||
var sinon = require('sinon') | ||
var shimmer = require('../index.js') | ||
var tap = require('tap') | ||
, test = tap.test | ||
, sinon = require('sinon') | ||
, shimmer = require('../index.js') | ||
; | ||
var outsider = 0 | ||
function counter () { return ++outsider } | ||
function anticounter () { return --outsider } | ||
var outsider = 0; | ||
function counter() { return ++outsider; } | ||
function anticounter() { return --outsider; } | ||
var generator = { | ||
inc : counter, | ||
dec : anticounter | ||
}; | ||
inc: counter, | ||
dec: anticounter | ||
} | ||
var arrow = { | ||
in : counter, | ||
out : anticounter | ||
}; | ||
in: counter, | ||
out: anticounter | ||
} | ||
var nester = { | ||
in : counter, | ||
out : anticounter | ||
}; | ||
in: counter, | ||
out: anticounter | ||
} | ||
test("should wrap multiple functions safely", function (t) { | ||
t.plan(9); | ||
test('should wrap multiple functions safely', function (t) { | ||
t.plan(9) | ||
t.equal(counter, generator.inc, "basic function equality testing should work"); | ||
t.equal(anticounter, generator.dec, "basic function equality testing should work"); | ||
t.doesNotThrow(function () { generator.inc(); }); | ||
t.doesNotThrow(function () { generator.dec(); }); | ||
t.equal(0, outsider, "calls have side effects"); | ||
t.equal(counter, generator.inc, 'basic function equality testing should work') | ||
t.equal(anticounter, generator.dec, 'basic function equality testing should work') | ||
t.doesNotThrow(function () { generator.inc() }) | ||
t.doesNotThrow(function () { generator.dec() }) | ||
t.equal(0, outsider, 'calls have side effects') | ||
var count = 0; | ||
function wrapper(original) { | ||
var count = 0 | ||
function wrapper (original) { | ||
return function () { | ||
count++; | ||
var returned = original.apply(this, arguments); | ||
count++; | ||
return returned; | ||
}; | ||
count++ | ||
var returned = original.apply(this, arguments) | ||
count++ | ||
return returned | ||
} | ||
} | ||
shimmer.massWrap(generator, ['inc', 'dec'], wrapper); | ||
shimmer.massWrap(generator, ['inc', 'dec'], wrapper) | ||
t.doesNotThrow(function () { generator.inc(); }); | ||
t.doesNotThrow(function () { generator.dec(); }); | ||
t.equal(4, count, "both pre and post increments should have happened"); | ||
t.equal(0, outsider, "original function has still been called"); | ||
}); | ||
t.doesNotThrow(function () { generator.inc() }) | ||
t.doesNotThrow(function () { generator.dec() }) | ||
t.equal(4, count, 'both pre and post increments should have happened') | ||
t.equal(0, outsider, 'original function has still been called') | ||
}) | ||
test("should wrap multiple functions on multiple modules safely", function (t) { | ||
t.plan(15); | ||
test('should wrap multiple functions on multiple modules safely', function (t) { | ||
t.plan(15) | ||
t.equal(counter, arrow.in, "basic function equality testing should work"); | ||
t.equal(counter, nester.in, "basic function equality testing should work"); | ||
t.equal(anticounter, arrow.out, "basic function equality testing should work"); | ||
t.equal(anticounter, nester.out, "basic function equality testing should work"); | ||
t.equal(counter, arrow.in, 'basic function equality testing should work') | ||
t.equal(counter, nester.in, 'basic function equality testing should work') | ||
t.equal(anticounter, arrow.out, 'basic function equality testing should work') | ||
t.equal(anticounter, nester.out, 'basic function equality testing should work') | ||
t.doesNotThrow(function () { arrow.in(); }); | ||
t.doesNotThrow(function () { nester.in(); }); | ||
t.doesNotThrow(function () { arrow.out(); }); | ||
t.doesNotThrow(function () { nester.out(); }); | ||
t.doesNotThrow(function () { arrow.in() }) | ||
t.doesNotThrow(function () { nester.in() }) | ||
t.doesNotThrow(function () { arrow.out() }) | ||
t.doesNotThrow(function () { nester.out() }) | ||
t.equal(0, outsider, "calls have side effects"); | ||
t.equal(0, outsider, 'calls have side effects') | ||
var count = 0; | ||
function wrapper(original) { | ||
var count = 0 | ||
function wrapper (original) { | ||
return function () { | ||
count++; | ||
var returned = original.apply(this, arguments); | ||
count++; | ||
return returned; | ||
}; | ||
count++ | ||
var returned = original.apply(this, arguments) | ||
count++ | ||
return returned | ||
} | ||
} | ||
shimmer.massWrap([arrow, nester], ['in', 'out'], wrapper); | ||
shimmer.massWrap([arrow, nester], ['in', 'out'], wrapper) | ||
t.doesNotThrow(function () { arrow.in(); }); | ||
t.doesNotThrow(function () { arrow.out(); }); | ||
t.doesNotThrow(function () { nester.in(); }); | ||
t.doesNotThrow(function () { nester.out(); }); | ||
t.doesNotThrow(function () { arrow.in() }) | ||
t.doesNotThrow(function () { arrow.out() }) | ||
t.doesNotThrow(function () { nester.in() }) | ||
t.doesNotThrow(function () { nester.out() }) | ||
t.equal(8, count, "both pre and post increments should have happened"); | ||
t.equal(0, outsider, "original function has still been called"); | ||
}); | ||
t.equal(8, count, 'both pre and post increments should have happened') | ||
t.equal(0, outsider, 'original function has still been called') | ||
}) | ||
test("wrap called with no arguments", function (t) { | ||
t.plan(2); | ||
test('wrap called with no arguments', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.twice(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.twice() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.massWrap(); | ||
}, "wrapping with no arguments doesn't throw"); | ||
shimmer.massWrap() | ||
}, "wrapping with no arguments doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with module but nothing else", function (t) { | ||
t.plan(2); | ||
test('wrap called with module but nothing else', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withExactArgs("must provide one or more functions to wrap on modules") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withExactArgs('must provide one or more functions to wrap on modules') | ||
.once() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.massWrap(generator); | ||
}, "wrapping with only 1 argument doesn't throw"); | ||
shimmer.massWrap(generator) | ||
}, "wrapping with only 1 argument doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with original but no wrapper", function (t) { | ||
t.plan(2); | ||
test('wrap called with original but no wrapper', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.twice(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.twice() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.massWrap(generator, ['inc']); | ||
}, "wrapping with only original function doesn't throw"); | ||
shimmer.massWrap(generator, ['inc']) | ||
}, "wrapping with only original function doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with non-function original", function (t) { | ||
t.plan(2); | ||
test('wrap called with non-function original', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withExactArgs("must provide one or more functions to wrap on modules") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withExactArgs('must provide one or more functions to wrap on modules') | ||
.once() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.massWrap({orange : 'slices'}, 'orange', function () {}); | ||
}, "wrapping non-function original doesn't throw"); | ||
shimmer.massWrap({orange: 'slices'}, 'orange', function () {}) | ||
}, "wrapping non-function original doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with non-function wrapper", function (t) { | ||
t.plan(2); | ||
test('wrap called with non-function wrapper', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withArgs("must provide one or more functions to wrap on modules") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withArgs('must provide one or more functions to wrap on modules') | ||
.once() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.massWrap({orange : function () {}}, 'orange', 'hamchunx'); | ||
}, "wrapping with non-function wrapper doesn't throw"); | ||
shimmer.massWrap({orange: function () {}}, 'orange', 'hamchunx') | ||
}, "wrapping with non-function wrapper doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) |
@@ -1,102 +0,101 @@ | ||
'use strict'; | ||
'use strict' | ||
var tap = require('tap') | ||
, test = tap.test | ||
, sinon = require('sinon') | ||
, shimmer = require('../index.js') | ||
; | ||
var tap = require('tap') | ||
var test = tap.test | ||
var sinon = require('sinon') | ||
var shimmer = require('../index.js') | ||
var outsider = 0; | ||
function counter() { return ++outsider; } | ||
var outsider = 0 | ||
function counter () { return ++outsider } | ||
var generator = { | ||
inc : counter | ||
}; | ||
inc: counter | ||
} | ||
test("should unwrap safely", function (t) { | ||
t.plan(9); | ||
test('should unwrap safely', function (t) { | ||
t.plan(9) | ||
t.equal(counter, generator.inc, "basic function equality testing should work"); | ||
t.doesNotThrow(function () { generator.inc(); }); | ||
t.equal(1, outsider, "calls have side effects"); | ||
t.equal(counter, generator.inc, 'basic function equality testing should work') | ||
t.doesNotThrow(function () { generator.inc() }) | ||
t.equal(1, outsider, 'calls have side effects') | ||
function wrapper(original) { | ||
function wrapper (original) { | ||
return function () { | ||
return original.apply(this, arguments); | ||
}; | ||
return original.apply(this, arguments) | ||
} | ||
} | ||
shimmer.wrap(generator, 'inc', wrapper); | ||
shimmer.wrap(generator, 'inc', wrapper) | ||
t.doesNotEqual(counter, generator.inc, "function should be wrapped"); | ||
t.doesNotEqual(counter, generator.inc, 'function should be wrapped') | ||
t.doesNotThrow(function () { generator.inc(); }); | ||
t.equal(2, outsider, "original function has still been called"); | ||
t.doesNotThrow(function () { generator.inc() }) | ||
t.equal(2, outsider, 'original function has still been called') | ||
shimmer.unwrap(generator, 'inc'); | ||
t.equal(counter, generator.inc, "basic function equality testing should work"); | ||
t.doesNotThrow(function () { generator.inc(); }); | ||
t.equal(3, outsider, "original function has still been called"); | ||
}); | ||
shimmer.unwrap(generator, 'inc') | ||
t.equal(counter, generator.inc, 'basic function equality testing should work') | ||
t.doesNotThrow(function () { generator.inc() }) | ||
t.equal(3, outsider, 'original function has still been called') | ||
}) | ||
test("shouldn't throw on double unwrapping", function (t) { | ||
t.plan(6); | ||
t.plan(6) | ||
t.equal(counter, generator.inc, "basic function equality testing should work"); | ||
t.equal(counter, generator.inc, 'basic function equality testing should work') | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withArgs("no original to unwrap to -- " + | ||
"has inc already been unwrapped?") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withArgs('no original to unwrap to -- ' + | ||
'has inc already been unwrapped?') | ||
.once() | ||
shimmer({logger: mock}) | ||
function wrapper(original) { | ||
function wrapper (original) { | ||
return function () { | ||
return original.apply(this, arguments); | ||
}; | ||
return original.apply(this, arguments) | ||
} | ||
} | ||
shimmer.wrap(generator, 'inc', wrapper); | ||
shimmer.wrap(generator, 'inc', wrapper) | ||
t.doesNotEqual(counter, generator.inc, "function should be wrapped"); | ||
t.doesNotEqual(counter, generator.inc, 'function should be wrapped') | ||
shimmer.unwrap(generator, 'inc'); | ||
t.equal(counter, generator.inc, "basic function equality testing should work"); | ||
shimmer.unwrap(generator, 'inc') | ||
t.equal(counter, generator.inc, 'basic function equality testing should work') | ||
t.doesNotThrow(function () { shimmer.unwrap(generator, 'inc'); }, | ||
"should double unwrap without issue"); | ||
t.equal(counter, generator.inc, "function is unchanged after unwrapping"); | ||
t.doesNotThrow(function () { shimmer.unwrap(generator, 'inc') }, | ||
'should double unwrap without issue') | ||
t.equal(counter, generator.inc, 'function is unchanged after unwrapping') | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("unwrap called with no arguments", function (t) { | ||
t.plan(2); | ||
test('unwrap called with no arguments', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.twice(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.twice() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { shimmer.unwrap(); }, "should log instead of throwing"); | ||
t.doesNotThrow(function () { shimmer.unwrap() }, 'should log instead of throwing') | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("unwrap called with module but no name", function (t) { | ||
t.plan(2); | ||
test('unwrap called with module but no name', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.twice(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.twice() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { shimmer.unwrap({}); }, "should log instead of throwing"); | ||
t.doesNotThrow(function () { shimmer.unwrap({}) }, 'should log instead of throwing') | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) |
@@ -1,128 +0,128 @@ | ||
'use strict'; | ||
'use strict' | ||
var tap = require('tap') | ||
, test = tap.test | ||
, sinon = require('sinon') | ||
, shimmer = require('../index.js') | ||
; | ||
var tap = require('tap') | ||
var test = tap.test | ||
var sinon = require('sinon') | ||
var shimmer = require('../index.js') | ||
var outsider = 0; | ||
function counter() { return ++outsider; } | ||
var outsider = 0 | ||
function counter () { return ++outsider } | ||
var generator = { | ||
inc : counter | ||
}; | ||
inc: counter | ||
} | ||
test("should wrap safely", function (t) { | ||
t.plan(8); | ||
test('should wrap safely', function (t) { | ||
t.plan(9) | ||
t.equal(counter, generator.inc, "method is mapped to function"); | ||
t.doesNotThrow(function () { generator.inc(); }, "original funciton works"); | ||
t.equal(1, outsider, "calls have side effects"); | ||
t.equal(counter, generator.inc, 'method is mapped to function') | ||
t.doesNotThrow(function () { generator.inc() }, 'original function works') | ||
t.equal(1, outsider, 'calls have side effects') | ||
var count = 0; | ||
function wrapper(original) { | ||
var count = 0 | ||
function wrapper (original, name) { | ||
t.equal(name, 'inc') | ||
return function () { | ||
count++; | ||
var returned = original.apply(this, arguments); | ||
count++; | ||
return returned; | ||
}; | ||
count++ | ||
var returned = original.apply(this, arguments) | ||
count++ | ||
return returned | ||
} | ||
} | ||
shimmer.wrap(generator, 'inc', wrapper); | ||
shimmer.wrap(generator, 'inc', wrapper) | ||
t.ok(generator.inc.__wrapped, "function tells us it's wrapped"); | ||
t.equal(generator.inc.__original, counter, "original function is available"); | ||
t.doesNotThrow(function () { generator.inc(); }, "wrapping works"); | ||
t.equal(2, count, "both pre and post increments should have happened"); | ||
t.equal(2, outsider, "original function has still been called"); | ||
}); | ||
t.ok(generator.inc.__wrapped, "function tells us it's wrapped") | ||
t.equal(generator.inc.__original, counter, 'original function is available') | ||
t.doesNotThrow(function () { generator.inc() }, 'wrapping works') | ||
t.equal(2, count, 'both pre and post increments should have happened') | ||
t.equal(2, outsider, 'original function has still been called') | ||
}) | ||
test("wrap called with no arguments", function (t) { | ||
t.plan(2); | ||
test('wrap called with no arguments', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withExactArgs("no original function undefined to wrap") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withExactArgs('no original function undefined to wrap') | ||
.once() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.wrap(); | ||
}, "wrapping with no arguments doesn't throw"); | ||
shimmer.wrap() | ||
}, "wrapping with no arguments doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with module but nothing else", function (t) { | ||
t.plan(2); | ||
test('wrap called with module but nothing else', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withExactArgs("no original function undefined to wrap") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withExactArgs('no original function undefined to wrap') | ||
.once() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.wrap(generator); | ||
}, "wrapping with only 1 argument doesn't throw"); | ||
shimmer.wrap(generator) | ||
}, "wrapping with only 1 argument doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with original but no wrapper", function (t) { | ||
t.plan(2); | ||
test('wrap called with original but no wrapper', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.twice(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.twice() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.wrap(generator, 'inc'); | ||
}, "wrapping with only original method doesn't throw"); | ||
shimmer.wrap(generator, 'inc') | ||
}, "wrapping with only original method doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with non-function original", function (t) { | ||
t.plan(2); | ||
test('wrap called with non-function original', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withExactArgs("original object and wrapper must be functions") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withExactArgs('original object and wrapper must be functions') | ||
.once() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.wrap({orange : 'slices'}, 'orange', function () {}); | ||
}, "wrapping non-function original doesn't throw"); | ||
shimmer.wrap({orange: 'slices'}, 'orange', function () {}) | ||
}, "wrapping non-function original doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) | ||
test("wrap called with non-function wrapper", function (t) { | ||
t.plan(2); | ||
test('wrap called with non-function wrapper', function (t) { | ||
t.plan(2) | ||
var mock = sinon.expectation | ||
.create('logger') | ||
.withArgs("original object and wrapper must be functions") | ||
.once(); | ||
shimmer({logger : mock}); | ||
.create('logger') | ||
.withArgs('original object and wrapper must be functions') | ||
.once() | ||
shimmer({logger: mock}) | ||
t.doesNotThrow(function () { | ||
shimmer.wrap({orange : function () {}}, 'orange', 'hamchunx'); | ||
}, "wrapping with non-function wrapper doesn't throw"); | ||
shimmer.wrap({orange: function () {}}, 'orange', 'hamchunx') | ||
}, "wrapping with non-function wrapper doesn't throw") | ||
t.doesNotThrow(function () { | ||
mock.verify(); | ||
}, "logger was called with the expected message"); | ||
}); | ||
mock.verify() | ||
}, 'logger was called with the expected message') | ||
}) |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
9
0
0
17642
3
422
75
1