aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.7/packages/api-utils/tests/test-functional.js
blob: 377a709ffd54da40f6a7fc3f6d69f6f090b38267 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const { setTimeout } = require('api-utils/timer');
const utils = require('api-utils/functional');
const { invoke, defer, curry, compose, memoize, once, delay, wrap } = utils;

exports['test forwardApply'] = function(assert) {
  function sum(b, c) this.a + b + c
  assert.equal(invoke(sum, [2, 3], { a: 1 }), 6,
               'passed arguments and pseoude-variable are used');

  assert.equal(invoke(sum.bind({ a: 2 }), [2, 3], { a: 1 }), 7,
               'bounded `this` pseoudo variable is used');
}

exports['test deferred function'] = function(assert, done) {
  let nextTurn = false;
  function sum(b, c) {
    assert.ok(nextTurn, 'enqueued is called in next turn of event loop');
    assert.equal(this.a + b + c, 6,
                 'passed arguments an pseoude-variable are used');
    done();
  }

  let fixture = { a: 1, method: defer(sum) }
  fixture.method(2, 3);
  nextTurn = true;
};

exports['test curry function'] = function(assert) {
  function sum(b, c) this.a + b + c;

  let foo = { a : 5 };

  foo.sum7 = curry(sum, 7);
  foo.sum8and4 = curry(sum, 8, 4);

  assert.equal(foo.sum7(2), 14, 'curry one arguments works');

  assert.equal(foo.sum8and4(), 17, 'curry both arguments works');
};

exports['test compose'] = function(assert) {
  let greet = function(name) { return 'hi: ' + name; };
  let exclaim = function(sentence) { return sentence + '!'; };

  assert.equal(compose(exclaim, greet)('moe'), 'hi: moe!',
               'can compose a function that takes another');

  assert.equal(compose(greet, exclaim)('moe'), 'hi: moe!',
               'in this case, the functions are also commutative');

  let target = {
    name: 'Joe',
    greet: compose(function exclaim(sentence) {
      return sentence + '!'
    }, function(title) {
      return 'hi : ' + title + ' ' + this.name;
    })
  }

  assert.equal(target.greet('Mr'), 'hi : Mr Joe!',
               'this can be passed in');
  assert.equal(target.greet.call({ name: 'Alex' }, 'Dr'), 'hi : Dr Alex!',
               'this can be applied');

  let single = compose(function(value) {
    return value + ':suffix';
  });

  assert.equal(single('text'), 'text:suffix', 'works with single function');

  let identity = compose();
  assert.equal(identity('bla'), 'bla', 'works with zero functions');
};

exports['test wrap'] = function(assert) {
  let greet = function(name) { return 'hi: ' + name; };
  let backwards = wrap(greet, function(f, name) {
    return f(name) + ' ' + name.split('').reverse().join('');
  });

  assert.equal(backwards('moe'), 'hi: moe eom',
               'wrapped the saluation function');

  let inner = function () { return 'Hello '; };
  let target = {
    name: 'Matteo',
    hi: wrap(inner, function(f) { return f() + this.name; })
  };

  assert.equal(target.hi(), 'Hello Matteo', 'works with this');

  function noop() { };
  let wrapped = wrap(noop, function(f) {
    return Array.slice(arguments);
  });

  let actual = wrapped([ 'whats', 'your' ], 'vector', 'victor');
  assert.deepEqual(actual, [ noop, ['whats', 'your'], 'vector', 'victor' ],
                   'works with fancy stuff');
};

exports['test memoize'] = function(assert) {
  function fib(n) n < 2 ? n : fib(n - 1) + fib(n - 2)
  let fibnitro = memoize(fib);

  assert.equal(fib(10), 55,
        'a memoized version of fibonacci produces identical results');
  assert.equal(fibnitro(10), 55,
        'a memoized version of fibonacci produces identical results');

  function o(key, value) { return value; };
  let oo = memoize(o), v1 = {}, v2 = {};


  assert.equal(oo(1, v1), v1, 'returns value back');
  assert.equal(oo(1, v2), v1, 'memoized by a first argument');
  assert.equal(oo(2, v2), v2, 'returns back value if not memoized');
  assert.equal(oo(2), v2, 'memoized new value');
  assert.notEqual(oo(1), oo(2), 'values do not override');
  assert.equal(o(3, v2), oo(2, 3), 'returns same value as un-memoized');

  let get = memoize(function(attribute) this[attribute])
  let target = { name: 'Bob', get: get }

  assert.equal(target.get('name'), 'Bob', 'has correct `this`');
  assert.equal(target.get.call({ name: 'Jack' }, 'name'), 'Bob',
               'name is memoized')
  assert.equal(get('name'), 'Bob', 'once memoized can be called without this');
};

exports['test delay'] = function(assert, done) {
  let delayed = false;
  delay(function() {
    assert.ok(delayed, 'delayed the function');
    done();
  }, 1);
  delayed = true;
};

exports['test delay with this'] = function(assert, done) {
  let context = {}
  delay.call(context, function(name) {
    assert.equal(this, context, 'this was passed in');
    assert.equal(name, 'Tom', 'argument was passed in');
    done();
  }, 10, 'Tom');
}

exports['test once'] = function(assert) {
  let n = 0;
  let increment = once(function() { n ++; });

  increment();
  increment();

  assert.equal(n, 1, 'only incremented once');

  let target = { state: 0, update: once(function() this.state ++ ) };

  target.update();
  target.update();

  assert.equal(target.state, 1, 'this was passed in and called only once');
};

require('test').run(exports);