cylon/spec/lib/utils/helpers.spec.js

379 lines
9.3 KiB
JavaScript

"use strict";
var _ = lib("utils/helpers");
describe("Helpers", function() {
describe("extend", function() {
var extend = _.extend;
var base = {
fruits: ["apple"],
vegetables: ["beet"],
thing: null,
otherThing: "hello!",
data: [{ user: "barney" }, { user: "fred" }]
};
var source = {
fruits: ["banana"],
vegetables: ["carrot"],
thing: "hello!",
otherThing: null,
data: [{ age: 36 }, { age: 40 }]
};
var expected = {
data: [ { age: 36, user: "barney" }, { age: 40, user: "fred" } ],
fruits: [ "apple", "banana" ],
vegetables: [ "beet", "carrot" ],
thing: "hello!",
otherThing: null
};
it("extends two objects", function() {
var extended = extend(base, source);
expect(extended).to.be.eql(expected);
});
});
describe("isObject", function() {
var fn = _.isObject;
it("checks if a value is an Object", function() {
var Klass = function() {},
instance = new Klass();
expect(fn({})).to.be.eql(true);
expect(fn(instance)).to.be.eql(true);
expect(fn([])).to.be.eql(false);
expect(fn(function() {})).to.be.eql(false);
expect(fn(10)).to.be.eql(false);
expect(fn("")).to.be.eql(false);
});
});
describe("isFunction", function() {
var fn = _.isFunction;
it("checks if a value is a Function", function() {
expect(fn(function() {})).to.be.eql(true);
expect(fn({})).to.be.eql(false);
expect(fn([])).to.be.eql(false);
expect(fn(10)).to.be.eql(false);
expect(fn("")).to.be.eql(false);
});
});
describe("isArray", function() {
var fn = _.isArray;
it("checks if a value is an Array", function() {
expect(fn([])).to.be.eql(true);
expect(fn(function() {})).to.be.eql(false);
expect(fn({})).to.be.eql(false);
expect(fn(10)).to.be.eql(false);
expect(fn("")).to.be.eql(false);
});
});
describe("isNumber", function() {
var fn = _.isNumber;
it("checks if a value is a Number", function() {
expect(fn(10)).to.be.eql(true);
expect(fn(function() {})).to.be.eql(false);
expect(fn({})).to.be.eql(false);
expect(fn([])).to.be.eql(false);
expect(fn("")).to.be.eql(false);
});
});
describe("isString", function() {
var fn = _.isString;
it("checks if a value is a String", function() {
expect(fn("")).to.be.eql(true);
expect(fn(10)).to.be.eql(false);
expect(fn(function() {})).to.be.eql(false);
expect(fn({})).to.be.eql(false);
expect(fn([])).to.be.eql(false);
});
});
describe("#pluck", function() {
var object = { a: { item: "hello" }, b: { item: "world" } },
array = [ { item: "hello" }, { item: "world" } ];
it("plucks values from a collection", function() {
expect(_.pluck(object, "item")).to.be.eql(["hello", "world"]);
expect(_.pluck(array, "item")).to.be.eql(["hello", "world"]);
});
});
describe("#map", function() {
var object = { a: { item: "hello" }, b: { item: "world" } },
array = [ { item: "hello" }, { item: "world" } ];
var fn = function(value, key) {
return [value, key];
};
it("runs a function over items in a collection", function() {
expect(_.map(object, fn)).to.be.eql([
[{ item: "hello" }, "a"],
[{ item: "world" }, "b"]
]);
expect(_.map(array, fn)).to.be.eql([
[{ item: "hello" }, 0],
[{ item: "world" }, 1]
]);
});
it("defaults to the identity function", function() {
expect(_.map(array)).to.be.eql(array);
expect(_.map(object)).to.be.eql(array);
});
});
describe("#invoke", function() {
var array = [
{
name: "bob",
toString: function() {
return "Hi from " + this.name;
}
},
{
name: "dave",
toString: function() {
return "hello from " + this.name;
}
}
];
var object = {
bob: {
name: "bob",
toString: function() {
return "Hi from " + this.name;
}
},
dave: {
name: "dave",
toString: function() {
return "hello from " + this.name;
}
}
};
it("runs a instance function over items in a collection", function() {
expect(_.invoke(object, "toString")).to.be.eql([
"Hi from bob",
"hello from dave"
]);
expect(_.invoke(array, "toString")).to.be.eql([
"Hi from bob",
"hello from dave"
]);
expect(_.invoke([1, 2, 3, 4, 5], Number.prototype.toString)).to.be.eql([
"1", "2", "3", "4", "5"
]);
});
});
describe("#each", function() {
var object = { a: { item: "hello" }, b: { item: "world" } },
array = [ { item: "hello" }, { item: "world" } ];
var fn = function(value, key) {
return [value, key];
};
it("runs a function over items in a collection", function() {
fn = spy();
_.map(object, fn);
expect(fn).to.be.calledWith(object.a, "a");
expect(fn).to.be.calledWith(object.b, "b");
fn = spy();
_.map(array, fn);
expect(fn).to.be.calledWith(array[0], 0);
expect(fn).to.be.calledWith(array[1], 1);
});
});
describe("#reduce", function() {
var arr = [1, 2, 3, 4, 5, 6],
obj = { a: 1, b: 2 };
function add(sum, n) { return sum + n; }
it("reduces over a collection with the provided iteratee", function() {
expect(_.reduce(arr, add, 0)).to.be.eql(21);
expect(_.reduce(obj, add, 0)).to.be.eql(3);
});
it("defaults to the first value for the accumulator", function() {
var object = {
a: { name: "hello" },
b: { name: "world" }
};
expect(_.reduce(arr, add)).to.be.eql(21);
expect(
_.reduce(object, function(acc, val) {
acc.name += " " + val.name;
return acc;
})
).to.be.eql({ name: "hello world"});
});
it("supports providing a `this` value", function() {
var self = {
toString: function(y) { return y.toString(); }
};
var fn = function(acc, val) {
return acc + this.toString(val);
};
expect(_.reduce(arr, fn, 1, self)).to.be.eql("123456");
});
});
describe("#arity", function() {
it("creates a function that only takes a certain # of args", function() {
var fn = spy();
var one = _.arity(fn, 1);
one("one", "two", "three");
expect(fn).to.be.calledWith("one");
});
});
describe("#partial", function() {
it("partially applies a function's arguments", function() {
var fn = spy();
var one = _.partial(fn, "one", "two");
one("three");
expect(fn).to.be.calledWith("one", "two", "three");
});
});
describe("#partialRight", function() {
it("partially applies arguments to the end of a fn call", function() {
var fn = spy();
var one = _.partialRight(fn, "two", "three");
one("one");
expect(fn).to.be.calledWith("one", "two", "three");
});
});
describe("#includes", function() {
it("checks if an array includes a value", function() {
var fn = _.includes;
var arr = [1, "2", 3];
expect(fn(arr, 1)).to.be.eql(true);
expect(fn(arr, "2")).to.be.eql(true);
expect(fn(arr, {})).to.be.eql(false);
});
});
describe("#parallel", function() {
var fn1, fn2, fn3, callback;
beforeEach(function() {
fn1 = stub();
fn2 = stub();
fn3 = stub();
callback = stub();
});
it("executes a set of functions in parallel", function() {
_.parallel([fn1, fn2, fn3], callback);
expect(fn1).to.be.called;
expect(fn2).to.be.called;
expect(fn3).to.be.called;
expect(callback).to.not.be.called;
fn1.yield(null, true);
expect(callback).to.not.be.called;
fn2.yield(null, true);
expect(callback).to.not.be.called;
fn3.yield(null, true);
expect(callback).to.be.calledWith(null, [true, true, true]);
});
it("stops immediately if there's an error", function() {
_.parallel([fn1, fn2, fn3], callback);
fn1.yield(true, null);
expect(callback).to.be.calledWith(true);
fn2.yields(null, true);
fn3.yields(null, true);
expect(callback).to.be.calledOnce;
});
});
describe("#series", function() {
var fn1, fn2, fn3, callback;
beforeEach(function() {
fn1 = stub();
fn2 = stub();
fn3 = stub();
callback = stub();
});
it("executes a set of functions in series", function() {
_.series([fn1, fn2, fn3], callback);
expect(fn1).to.be.called;
expect(fn2).to.not.be.called;
expect(fn3).to.not.be.called;
expect(callback).to.not.be.called;
fn1.yield(null, true);
expect(fn2).to.be.called;
expect(fn3).to.not.be.called;
expect(callback).to.not.be.called;
fn2.yield(null, true);
expect(fn3).to.be.called;
expect(callback).to.not.be.called;
fn3.yield(null, true);
expect(callback).to.be.calledWith(null, [true, true, true]);
});
it("stops immediately if there's an error", function() {
_.series([fn1, fn2, fn3], callback);
fn1.yield(true, null);
expect(fn2).to.not.be.called;
expect(fn3).to.not.be.called;
expect(callback).to.be.calledWith(true);
});
});
});