diff --git a/README.md b/README.md index 1e89449..50303a8 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,13 @@ var count = normalize('number', function(a, b) { }, 1, 2); // count === 3 +// Supply the function with context +var context = { c: 3 }; +var count = normalize.call(context, 'number', function(a, b) { + return a + b + this.c; +}, 1, 2); +// count === 6 + // Values one of multiple types are returned var isEnabled = normalize(['string', 'boolean'], true); // isEnabled === true diff --git a/index.js b/index.js index 0002f70..b68af8d 100644 --- a/index.js +++ b/index.js @@ -18,31 +18,31 @@ function normalize(coercer, value) { if (coercer === 'function') { return value; } - value = value.apply(null, Array.prototype.slice.call(arguments, 2)); + value = value.apply(this, slice(arguments, 2)); } - return coerce(coercer, value); + return coerce(this, coercer, value); } -function coerce(coercer, value) { +function coerce(ctx, coercer, value) { // Handle built-in types if (typeof coercer === 'string') { if (coerce[coercer]) { - return coerce[coercer](value); + return coerce[coercer].call(ctx, value); } return typeOf(coercer, value); } // Handle custom coercer if (typeof coercer === 'function') { - return coercer(value); + return coercer.call(ctx, value); } // Array of coercers, try in order until one returns a non-null value var result = null; coercer.some(function(coercer) { - result = coerce(coercer, value); + result = coerce(ctx, coercer, value); return result !== null; }); @@ -98,11 +98,19 @@ function primitive(value) { return value; } +function slice(value, from) { + return Array.prototype.slice.call(value, from); +} // Add methods for each type types.forEach(function(type) { - normalize[type] = normalize.bind(null, type); -}); + // Make it an array for easier concat + var typeArg = [type]; + normalize[type] = function() { + var args = slice(arguments); + return normalize.apply(this, typeArg.concat(args)); + }; +}); module.exports = normalize; diff --git a/test/index.js b/test/index.js index 59d84a1..6e7f08a 100644 --- a/test/index.js +++ b/test/index.js @@ -46,17 +46,17 @@ describe('normalize', function() { done(); }); - it('supports functions for the type parameter', function(done) { + it('supports coercer functions for the type parameter', function(done) { var type = function() { return true; }; var value = 1; var result = normalize(type, value); - expect(result).toEqual(value); + expect(result).toBe(true); done(); }); - it('calls the type function to attempt coercion', function(done) { + it('calls the coercer function to attempt coercion', function(done) { var expected = 1; var type = expect.createSpy().andCall(function(value) { return value; @@ -67,6 +67,19 @@ describe('normalize', function() { done(); }); + it('calls the coercer functions with context, if bound', function(done) { + var expected = 1; + var context = {}; + var type = expect.createSpy().andCall(function(value) { + expect(this).toBe(context); + return value; + }); + var result = normalize.call(context, type, expected); + expect(result).toEqual(expected); + expect(type).toHaveBeenCalled(); + done(); + }); + it('calls the value if it is a function', function(done) { var type = 'string'; var expected = 'test string'; @@ -79,6 +92,17 @@ describe('normalize', function() { done(); }); + it('calls the value function with context, if bound', function(done) { + var type = 'string'; + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.call(context, type, value); + expect(value).toHaveBeenCalled(); + done(); + }); + it('checks the result of function against coercer', function(done) { var expected = 'test string'; var coercer = expect.createSpy().andCall(function(value) { @@ -163,6 +187,16 @@ describe('normalize.object', function() { expect(result).toEqual(null); done(); }); + + it('calls the object function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.object.call(context, value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.number', function() { @@ -202,6 +236,16 @@ describe('normalize.number', function() { expect(result).toEqual(null); done(); }); + + it('calls the number function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.number.call(context, value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.string', function() { @@ -250,6 +294,16 @@ describe('normalize.string', function() { expect(result).toEqual(null); done(); }); + + it('calls the string function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.string.call(context, value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.symbol', function() { @@ -278,6 +332,21 @@ describe('normalize.symbol', function() { expect(result).toEqual(null); done(); }); + + it('calls the symbol function with context, if bound', function(done) { + if (!global.Symbol) { + console.log('Only available on platforms that support Symbol'); + this.skip(); + return; + } + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.symbol.call(context, value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.boolean', function() { @@ -303,6 +372,16 @@ describe('normalize.boolean', function() { expect(result).toEqual(null); done(); }); + + it('calls the boolean function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.boolean.call(context, value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.function', function() { @@ -345,6 +424,16 @@ describe('normalize.undefined', function() { expect(result).toEqual(null); done(); }); + + it('calls the undefined function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.undefined.call(context, value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.date', function() { @@ -413,4 +502,14 @@ describe('normalize.date', function() { expect(result).toEqual(null); done(); }); + + it('calls the date function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.date.call(context, value); + expect(value).toHaveBeenCalled(); + done(); + }); });