opusdev/vector-similarity-api
1
1// jscs:disable requireUseStrict2 3var test = require('tape');4 5var functionBind = require('../implementation');6var getCurrentContext = function () { return this; };7 8test('functionBind is a function', function (t) {9 t.equal(typeof functionBind, 'function');10 t.end();11});12 13test('non-functions', function (t) {14 var nonFunctions = [true, false, [], {}, 42, 'foo', NaN, /a/g];15 t.plan(nonFunctions.length);16 for (var i = 0; i < nonFunctions.length; ++i) {17 try { functionBind.call(nonFunctions[i]); } catch (ex) {18 t.ok(ex instanceof TypeError, 'throws when given ' + String(nonFunctions[i]));19 }20 }21 t.end();22});23 24test('without a context', function (t) {25 t.test('binds properly', function (st) {26 var args, context;27 var namespace = {28 func: functionBind.call(function () {29 args = Array.prototype.slice.call(arguments);30 context = this;31 })32 };33 namespace.func(1, 2, 3);34 st.deepEqual(args, [1, 2, 3]);35 st.equal(context, getCurrentContext.call());36 st.end();37 });38 39 t.test('binds properly, and still supplies bound arguments', function (st) {40 var args, context;41 var namespace = {42 func: functionBind.call(function () {43 args = Array.prototype.slice.call(arguments);44 context = this;45 }, undefined, 1, 2, 3)46 };47 namespace.func(4, 5, 6);48 st.deepEqual(args, [1, 2, 3, 4, 5, 6]);49 st.equal(context, getCurrentContext.call());50 st.end();51 });52 53 t.test('returns properly', function (st) {54 var args;55 var namespace = {56 func: functionBind.call(function () {57 args = Array.prototype.slice.call(arguments);58 return this;59 }, null)60 };61 var context = namespace.func(1, 2, 3);62 st.equal(context, getCurrentContext.call(), 'returned context is namespaced context');63 st.deepEqual(args, [1, 2, 3], 'passed arguments are correct');64 st.end();65 });66 67 t.test('returns properly with bound arguments', function (st) {68 var args;69 var namespace = {70 func: functionBind.call(function () {71 args = Array.prototype.slice.call(arguments);72 return this;73 }, null, 1, 2, 3)74 };75 var context = namespace.func(4, 5, 6);76 st.equal(context, getCurrentContext.call(), 'returned context is namespaced context');77 st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'passed arguments are correct');78 st.end();79 });80 81 t.test('called as a constructor', function (st) {82 var thunkify = function (value) {83 return function () { return value; };84 };85 st.test('returns object value', function (sst) {86 var expectedReturnValue = [1, 2, 3];87 var Constructor = functionBind.call(thunkify(expectedReturnValue), null);88 var result = new Constructor();89 sst.equal(result, expectedReturnValue);90 sst.end();91 });92 93 st.test('does not return primitive value', function (sst) {94 var Constructor = functionBind.call(thunkify(42), null);95 var result = new Constructor();96 sst.notEqual(result, 42);97 sst.end();98 });99 100 st.test('object from bound constructor is instance of original and bound constructor', function (sst) {101 var A = function (x) {102 this.name = x || 'A';103 };104 var B = functionBind.call(A, null, 'B');105 106 var result = new B();107 sst.ok(result instanceof B, 'result is instance of bound constructor');108 sst.ok(result instanceof A, 'result is instance of original constructor');109 sst.end();110 });111 112 st.end();113 });114 115 t.end();116});117 118test('with a context', function (t) {119 t.test('with no bound arguments', function (st) {120 var args, context;121 var boundContext = {};122 var namespace = {123 func: functionBind.call(function () {124 args = Array.prototype.slice.call(arguments);125 context = this;126 }, boundContext)127 };128 namespace.func(1, 2, 3);129 st.equal(context, boundContext, 'binds a context properly');130 st.deepEqual(args, [1, 2, 3], 'supplies passed arguments');131 st.end();132 });133 134 t.test('with bound arguments', function (st) {135 var args, context;136 var boundContext = {};137 var namespace = {138 func: functionBind.call(function () {139 args = Array.prototype.slice.call(arguments);140 context = this;141 }, boundContext, 1, 2, 3)142 };143 namespace.func(4, 5, 6);144 st.equal(context, boundContext, 'binds a context properly');145 st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'supplies bound and passed arguments');146 st.end();147 });148 149 t.test('returns properly', function (st) {150 var boundContext = {};151 var args;152 var namespace = {153 func: functionBind.call(function () {154 args = Array.prototype.slice.call(arguments);155 return this;156 }, boundContext)157 };158 var context = namespace.func(1, 2, 3);159 st.equal(context, boundContext, 'returned context is bound context');160 st.notEqual(context, getCurrentContext.call(), 'returned context is not lexical context');161 st.deepEqual(args, [1, 2, 3], 'passed arguments are correct');162 st.end();163 });164 165 t.test('returns properly with bound arguments', function (st) {166 var boundContext = {};167 var args;168 var namespace = {169 func: functionBind.call(function () {170 args = Array.prototype.slice.call(arguments);171 return this;172 }, boundContext, 1, 2, 3)173 };174 var context = namespace.func(4, 5, 6);175 st.equal(context, boundContext, 'returned context is bound context');176 st.notEqual(context, getCurrentContext.call(), 'returned context is not lexical context');177 st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'passed arguments are correct');178 st.end();179 });180 181 t.test('passes the correct arguments when called as a constructor', function (st) {182 var expected = { name: 'Correct' };183 var namespace = {184 Func: functionBind.call(function (arg) {185 return arg;186 }, { name: 'Incorrect' })187 };188 var returned = new namespace.Func(expected);189 st.equal(returned, expected, 'returns the right arg when called as a constructor');190 st.end();191 });192 193 t.test('has the new instance\'s context when called as a constructor', function (st) {194 var actualContext;195 var expectedContext = { foo: 'bar' };196 var namespace = {197 Func: functionBind.call(function () {198 actualContext = this;199 }, expectedContext)200 };201 var result = new namespace.Func();202 st.equal(result instanceof namespace.Func, true);203 st.notEqual(actualContext, expectedContext);204 st.end();205 });206 207 t.end();208});209 210test('bound function length', function (t) {211 t.test('sets a correct length without thisArg', function (st) {212 var subject = functionBind.call(function (a, b, c) { return a + b + c; });213 st.equal(subject.length, 3);214 st.equal(subject(1, 2, 3), 6);215 st.end();216 });217 218 t.test('sets a correct length with thisArg', function (st) {219 var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {});220 st.equal(subject.length, 3);221 st.equal(subject(1, 2, 3), 6);222 st.end();223 });224 225 t.test('sets a correct length without thisArg and first argument', function (st) {226 var subject = functionBind.call(function (a, b, c) { return a + b + c; }, undefined, 1);227 st.equal(subject.length, 2);228 st.equal(subject(2, 3), 6);229 st.end();230 });231 232 t.test('sets a correct length with thisArg and first argument', function (st) {233 var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {}, 1);234 st.equal(subject.length, 2);235 st.equal(subject(2, 3), 6);236 st.end();237 });238 239 t.test('sets a correct length without thisArg and too many arguments', function (st) {240 var subject = functionBind.call(function (a, b, c) { return a + b + c; }, undefined, 1, 2, 3, 4);241 st.equal(subject.length, 0);242 st.equal(subject(), 6);243 st.end();244 });245 246 t.test('sets a correct length with thisArg and too many arguments', function (st) {247 var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {}, 1, 2, 3, 4);248 st.equal(subject.length, 0);249 st.equal(subject(), 6);250 st.end();251 });252});253 