simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

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 });