2015-02-21 10:49:31 +08:00
|
|
|
"use strict";
|
|
|
|
|
2015-06-09 22:21:03 +08:00
|
|
|
var _ = lib("utils/helpers");
|
2015-02-21 10:49:31 +08:00
|
|
|
|
|
|
|
describe("Helpers", function() {
|
|
|
|
describe("extend", function() {
|
|
|
|
var extend = _.extend;
|
|
|
|
|
|
|
|
var base = {
|
|
|
|
fruits: ["apple"],
|
|
|
|
vegetables: ["beet"],
|
|
|
|
thing: null,
|
|
|
|
otherThing: "hello!",
|
2015-04-15 12:49:12 +08:00
|
|
|
data: [{ user: "barney" }, { user: "fred" }]
|
2015-02-21 10:49:31 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
var source = {
|
|
|
|
fruits: ["banana"],
|
|
|
|
vegetables: ["carrot"],
|
|
|
|
thing: "hello!",
|
|
|
|
otherThing: null,
|
2015-04-15 12:49:12 +08:00
|
|
|
data: [{ age: 36 }, { age: 40 }]
|
2015-02-21 10:49:31 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
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() {
|
2015-04-15 12:49:12 +08:00
|
|
|
var fn = _.isObject;
|
2015-02-21 10:49:31 +08:00
|
|
|
|
|
|
|
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() {
|
2015-04-15 12:49:12 +08:00
|
|
|
var fn = _.isFunction;
|
2015-02-21 10:49:31 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-02-24 07:20:50 +08:00
|
|
|
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() {
|
2015-04-15 12:49:12 +08:00
|
|
|
var object = {
|
2015-02-24 07:20:50 +08:00
|
|
|
a: { name: "hello" },
|
|
|
|
b: { name: "world" }
|
|
|
|
};
|
|
|
|
|
|
|
|
expect(_.reduce(arr, add)).to.be.eql(21);
|
|
|
|
expect(
|
2015-04-15 12:49:12 +08:00
|
|
|
_.reduce(object, function(acc, val) {
|
2015-02-24 07:20:50 +08:00
|
|
|
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");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-02-21 10:49:31 +08:00
|
|
|
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");
|
|
|
|
});
|
|
|
|
});
|
2015-02-24 06:31:52 +08:00
|
|
|
|
|
|
|
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");
|
|
|
|
});
|
|
|
|
});
|
2015-03-12 03:31:45 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
});
|
|
|
|
});
|
2015-06-19 05:57:41 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
});
|
|
|
|
});
|
2015-02-21 10:49:31 +08:00
|
|
|
});
|