rest_params.js (8255B)
1 var assert = require('assert'); 2 var typed = require('../typed-function'); 3 var strictEqualArray = require('./strictEqualArray'); 4 5 describe('rest parameters', function () { 6 7 it('should create a typed function with rest parameters', function() { 8 var sum = typed({ 9 '...number': function (values) { 10 assert(Array.isArray(values)); 11 var sum = 0; 12 for (var i = 0; i < values.length; i++) { 13 sum += values[i]; 14 } 15 return sum; 16 } 17 }); 18 19 assert.equal(sum(2), 2); 20 assert.equal(sum(2,3,4), 9); 21 assert.throws(function () {sum()}, /TypeError: Too few arguments in function unnamed \(expected: number, index: 0\)/); 22 assert.throws(function () {sum(true)}, /TypeError: Unexpected type of argument in function unnamed \(expected: number, actual: boolean, index: 0\)/); 23 assert.throws(function () {sum('string')}, /TypeError: Unexpected type of argument in function unnamed \(expected: number, actual: string, index: 0\)/); 24 assert.throws(function () {sum(2, 'string')}, /TypeError: Unexpected type of argument in function unnamed \(expected: number, actual: string, index: 1\)/); 25 assert.throws(function () {sum(2, 3, 'string')}, /TypeError: Unexpected type of argument in function unnamed \(expected: number, actual: string, index: 2\)/); 26 }); 27 28 it('should create a typed function with rest parameters (2)', function() { 29 var fn = typed({ 30 'string, ...number': function (str, values) { 31 assert.equal(typeof str, 'string'); 32 assert(Array.isArray(values)); 33 return str + ': ' + values.join(', '); 34 } 35 }); 36 37 assert.equal(fn('foo', 2), 'foo: 2'); 38 assert.equal(fn('foo', 2, 4), 'foo: 2, 4'); 39 assert.throws(function () {fn(2, 4)}, /TypeError: Unexpected type of argument in function unnamed \(expected: string, actual: number, index: 0\)/); 40 assert.throws(function () {fn('string')}, /TypeError: Too few arguments in function unnamed \(expected: number, index: 1\)/); 41 assert.throws(function () {fn('string', 'string')}, /TypeError: Unexpected type of argument in function unnamed \(expected: number, actual: string, index: 1\)/); 42 }); 43 44 it('should create a typed function with any type arguments (1)', function() { 45 var fn = typed({ 46 'string, ...any': function (str, values) { 47 assert.equal(typeof str, 'string'); 48 assert(Array.isArray(values)); 49 return str + ': ' + values.join(', '); 50 } 51 }); 52 53 assert.equal(fn('foo', 2), 'foo: 2'); 54 assert.equal(fn('foo', 2, true, 'bar'), 'foo: 2, true, bar'); 55 assert.equal(fn('foo', 'bar'), 'foo: bar'); 56 assert.throws(function () {fn(2, 4)}, /TypeError: Unexpected type of argument in function unnamed \(expected: string, actual: number, index: 0\)/); 57 assert.throws(function () {fn('string')}, /TypeError: Too few arguments in function unnamed \(expected: any, index: 1\)/); 58 }); 59 60 it('should create a typed function with implicit any type arguments', function() { 61 var fn = typed({ 62 'string, ...': function (str, values) { 63 assert.equal(typeof str, 'string'); 64 assert(Array.isArray(values)); 65 return str + ': ' + values.join(', '); 66 } 67 }); 68 69 assert.equal(fn('foo', 2), 'foo: 2'); 70 assert.equal(fn('foo', 2, true, 'bar'), 'foo: 2, true, bar'); 71 assert.equal(fn('foo', 'bar'), 'foo: bar'); 72 assert.throws(function () {fn(2, 4)}, /TypeError: Unexpected type of argument in function unnamed \(expected: string, actual: number, index: 0\)/); 73 assert.throws(function () {fn('string')}, /TypeError: Too few arguments in function unnamed \(expected: any, index: 1\)/); 74 }); 75 76 it('should create a typed function with any type arguments (2)', function() { 77 var fn = typed({ 78 'any, ...number': function (any, values) { 79 assert(Array.isArray(values)); 80 return any + ': ' + values.join(', '); 81 } 82 }); 83 84 assert.equal(fn('foo', 2), 'foo: 2'); 85 assert.equal(fn(1, 2, 4), '1: 2, 4'); 86 assert.equal(fn(null, 2, 4), 'null: 2, 4'); 87 assert.throws(function () {fn('string')}, /TypeError: Too few arguments in function unnamed \(expected: number, index: 1\)/); 88 assert.throws(function () {fn('string', 'string')}, /TypeError: Unexpected type of argument in function unnamed \(expected: number, actual: string, index: 1\)/); 89 }); 90 91 it('should create a typed function with union type arguments', function() { 92 var fn = typed({ 93 '...number|string': function (values) { 94 assert(Array.isArray(values)); 95 return values; 96 } 97 }); 98 99 strictEqualArray(fn(2,3,4), [2,3,4]); 100 strictEqualArray(fn('a','b','c'), ['a','b','c']); 101 strictEqualArray(fn('a',2,'c',3), ['a',2,'c',3]); 102 assert.throws(function () {fn()}, /TypeError: Too few arguments in function unnamed \(expected: number or string, index: 0\)/); 103 assert.throws(function () {fn('string', true)}, /TypeError: Unexpected type of argument. Index: 1 in function unnamed \(expected: string | number/); 104 assert.throws(function () {fn(2, false)}, /TypeError: Unexpected type of argument. Index: 1 in function unnamed \(expected: string | number/); 105 assert.throws(function () {fn(2, 3, false)}, /TypeError: Unexpected type of argument. Index: 2 in function unnamed \(expected: string | number/); 106 }); 107 108 it('should create a composed function with rest parameters', function() { 109 var fn = typed({ 110 'string, ...number': function (str, values) { 111 assert.equal(typeof str, 'string'); 112 assert(Array.isArray(values)); 113 return str + ': ' + values.join(', '); 114 }, 115 116 '...boolean': function (values) { 117 assert(Array.isArray(values)); 118 return 'booleans'; 119 } 120 }); 121 122 assert.equal(fn('foo', 2), 'foo: 2'); 123 assert.equal(fn('foo', 2, 4), 'foo: 2, 4'); 124 assert.equal(fn(true, false, false), 'booleans'); 125 assert.throws(function () {fn(2, 4)}, /TypeError: Unexpected type of argument in function unnamed \(expected: string or boolean, actual: number, index: 0\)/); 126 assert.throws(function () {fn('string')}, /TypeError: Too few arguments in function unnamed \(expected: number, index: 1\)/); 127 assert.throws(function () {fn('string', true)}, /TypeError: Unexpected type of argument in function unnamed \(expected: number, actual: boolean, index: 1\)/); 128 }); 129 130 it('should continue with other options if rest params do not match', function() { 131 var fn = typed({ 132 '...number': function (values) { 133 return '...number'; 134 }, 135 136 'Object': function (value) { 137 return 'Object'; 138 } 139 }); 140 141 assert.equal(fn(2, 3), '...number'); 142 assert.equal(fn(2), '...number'); 143 assert.equal(fn({}), 'Object'); 144 assert.deepEqual(Object.keys(fn.signatures), [ 145 'Object', 146 '...number' 147 ]); 148 }); 149 150 it('should split rest params with conversions in two and order them correctly', function() { 151 var typed2 = typed.create() 152 typed2.conversions = [ 153 {from: 'string', to: 'number', convert: function (x) {return parseFloat(x)}} 154 ]; 155 156 var fn = typed2({ 157 '...number': function (values) { 158 return values; 159 }, 160 161 '...string': function (value) { 162 return value; 163 } 164 }); 165 166 assert.deepEqual(fn(2, 3), [2,3]); 167 assert.deepEqual(fn(2), [2]); 168 assert.deepEqual(fn(2, '4'), [2, 4]); 169 assert.deepEqual(fn('2', 4), [2, 4]); 170 assert.deepEqual(fn('foo'), ['foo']); 171 assert.deepEqual(Object.keys(fn.signatures), [ 172 '...number', 173 '...string' 174 ]); 175 }); 176 177 it('should throw an error in case of unexpected rest parameters', function() { 178 assert.throws(function () { 179 typed({'...number, string': function () {}}); 180 }, /SyntaxError: Unexpected rest parameter "...number": only allowed for the last parameter/); 181 }); 182 183 it('should correctly interact with any', function() { 184 var fn = typed({ 185 'string': function () { 186 return 'one'; 187 }, 188 '...any': function () { 189 return 'two'; 190 } 191 }); 192 193 assert.equal(fn('a'), 'one'); 194 assert.equal(fn([]), 'two'); 195 assert.equal(fn('a','a'), 'two'); 196 assert.equal(fn('a',[]), 'two'); 197 assert.equal(fn([],[]), 'two'); 198 }); 199 200 });