simple-squiggle

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

merge.test.js (4519B)


      1 var assert = require('assert');
      2 var typed = require('../typed-function');
      3 
      4 describe('merge', function () {
      5   it('should merge two typed-functions', function () {
      6     var typed1 = typed({'boolean': function (value) { return 'boolean:' + value; }});
      7     var typed2 = typed({'number':  function (value) { return 'number:' + value;  }});
      8 
      9     var typed3 = typed(typed1, typed2);
     10 
     11     assert.deepEqual(Object.keys(typed3.signatures).sort(), ['boolean', 'number']);
     12 
     13     assert.strictEqual(typed3(true), 'boolean:true');
     14     assert.strictEqual(typed3(2), 'number:2');
     15     assert.throws(function () {typed3('foo')}, /TypeError: Unexpected type of argument in function unnamed \(expected: number or boolean, actual: string, index: 0\)/);
     16   });
     17 
     18   it('should merge three typed-functions', function () {
     19     var typed1 = typed({'boolean': function (value) { return 'boolean:' + value; }});
     20     var typed2 = typed({'number':  function (value) { return 'number:' + value;  }});
     21     var typed3 = typed({'string':  function (value) { return 'string:' + value;  }});
     22 
     23     var typed4 = typed(typed1, typed2, typed3);
     24 
     25     assert.deepEqual(Object.keys(typed4.signatures).sort(), ['boolean', 'number', 'string']);
     26 
     27     assert.strictEqual(typed4(true), 'boolean:true');
     28     assert.strictEqual(typed4(2), 'number:2');
     29     assert.strictEqual(typed4('foo'), 'string:foo');
     30     assert.throws(function () {typed4(new Date())}, /TypeError: Unexpected type of argument in function unnamed \(expected: number or string or boolean, actual: Date, index: 0\)/);
     31   });
     32 
     33   it('should merge two typed-functions with a custom name', function () {
     34     var typed1 = typed('typed1', {'boolean': function (value) { return 'boolean:' + value; }});
     35     var typed2 = typed('typed2', {'number':  function (value) { return 'number:' + value;  }});
     36 
     37     var typed3 = typed('typed3', typed1, typed2);
     38 
     39     assert.equal(typed3.name, 'typed3');
     40   });
     41 
     42   it('should not copy conversions as exact signatures', function () {
     43     var typed2 = typed.create();
     44     typed2.conversions = [
     45       {from: 'string', to: 'number', convert: function (x) {return parseFloat(x)}}
     46     ];
     47 
     48     var fn2 = typed2({'number': function (value) { return value }});
     49 
     50     assert.strictEqual(fn2(2), 2);
     51     assert.strictEqual(fn2('123'), 123);
     52 
     53     var fn1 = typed({ 'Date': function (value) {return value} });
     54     var fn3 = typed(fn1, fn2); // create via typed which has no conversions
     55 
     56     var date = new Date()
     57     assert.strictEqual(fn3(2), 2);
     58     assert.strictEqual(fn3(date), date);
     59     assert.throws(function () {fn3('123') }, /TypeError: Unexpected type of argument in function unnamed \(expected: number or Date, actual: string, index: 0\)/);
     60   });
     61 
     62   it('should allow merging duplicate signatures when pointing to the same function', function () {
     63     var typed1 = typed({'boolean': function (value) { return 'boolean:' + value; }});
     64 
     65     var merged = typed(typed1, typed1);
     66 
     67     assert.deepEqual(Object.keys(merged.signatures).sort(), ['boolean']);
     68   });
     69 
     70   it('should throw an error in case of conflicting signatures when merging', function () {
     71     var typed1 = typed({'boolean': function (value) { return 'boolean:' + value; }});
     72     var typed2 = typed({'boolean': function (value) { return 'boolean:' + value; }});
     73 
     74     assert.throws(function () {
     75       typed(typed1, typed2)
     76     }, /Error: Signature "boolean" is defined twice/);
     77   });
     78 
     79   it('should throw an error in case of conflicting names when merging', function () {
     80     var typed1 = typed('fn1', {'boolean': function () {}});
     81     var typed2 = typed('fn2', {'string': function () {}});
     82     var typed3 = typed({'number': function () {}});
     83 
     84     assert.throws(function () {
     85       typed(typed1, typed2)
     86     }, /Error: Function names do not match \(expected: fn1, actual: fn2\)/);
     87 
     88     var typed4 = typed(typed2, typed3);
     89     assert.equal(typed4.name, 'fn2');
     90   });
     91 
     92   it('should allow recursive across merged signatures', function () {
     93     var fn1 = typed({
     94       '...number': function (values) {
     95         var sum = 0;
     96         for (var i = 0; i < values.length; i++) {
     97           sum += values[i];
     98         }
     99         return sum;
    100       }
    101     });
    102 
    103     var fn2 = typed({
    104       '...string': function (values) {
    105         var newValues = [];
    106         for (var i = 0; i < values.length; i++) {
    107           newValues[i] = parseInt(values[i], 10);
    108         }
    109         return this.apply(null, newValues);
    110       }
    111     });
    112 
    113     var fn3 = typed(fn1, fn2);
    114 
    115     assert.equal(fn3('1', '2', '3'), '6');
    116     assert.equal(fn3(1, 2, 3), 6);
    117   })
    118 });