activestack-gateway
Version:
Socket server for ActiveStack
301 lines (260 loc) • 12.7 kB
JavaScript
/// <reference path="../chance.js" />
/// <reference path="../node_modules/underscore/underscore-min.js" />
var expect = chai.expect;
describe("Helpers", function () {
var word, arr, picked, chance = new Chance();
describe("capitalize works as expected", function () {
it("returns a random name", function () {
_(1000).times(function () {
word = chance.capitalize(chance.word());
expect(word).to.be.a('string');
expect(word[0]).to.match(/[A-Z]/);
});
});
});
describe("pick()", function () {
it("returns a single element when called without a count argument", function () {
arr = ['a', 'b', 'c', 'd'];
_(1000).times(function () {
picked = chance.pick(arr);
expect(picked).to.have.length(1);
});
});
it("returns multiple elements when called with a count argument", function () {
arr = ['a', 'b', 'c', 'd'];
_(1000).times(function () {
picked = chance.pick(arr, 3);
expect(picked).to.have.length(3);
});
});
it("doesn't destroy the original array when called with a count argument", function () {
arr = ['a', 'b', 'c', 'd', 'e', 'f'];
_(1000).times(function () {
picked = chance.pick(arr, 3);
expect(arr).to.have.length(6);
});
});
it("throws good error if zero elements in array", function () {
arr = [];
expect(function () {
chance.pick(arr);
}).to.throw(RangeError, "Chance: Cannot pick() from an empty array");
});
});
describe("weighted()", function () {
this.timeout(10000);
it("returns an element", function () {
_(1000).times(function () {
picked = chance.weighted(['a', 'b', 'c', 'd'], [1, 1, 1, 1]);
expect(picked).to.be.a('string');
});
});
it("works with just 2 items", function() {
// Use Math.random as the random function rather than our Mersenne twister just to
// speed things up here because this test takes awhile to gather enough data to
// have a large enough sample size to adequately test. This increases speed
// by a few orders of magnitude at the cost of repeatability (which we aren't using here)
var chance = new Chance(Math.random);
var picked = { a: 0, b: 0 };
// This makes it a tad slow, but we need a large enough sample size to adequately test
_(50000).times(function () {
picked[chance.weighted(['a', 'b'], [1, 100])]++;
});
// This range is somewhat arbitrary, but good enough to test our constraints
expect(picked.b / picked.a).to.be.within(80, 120);
picked = { a: 0, b: 0 };
// This makes it a tad slow, but we need a large enough sample size to adequately test
_(50000).times(function () {
picked[chance.weighted(['a', 'b'], [100, 1])]++;
});
// This range is somewhat arbitrary, but good enough to test our constraints
expect(picked.a / picked.b).to.be.within(80, 120);
});
it("throws an error if called with an array of weights with length different from options", function() {
expect(function () {
chance.weighted(['a', 'b', 'c', 'd'], [1, 2, 3]);
}).to.throw(RangeError, /length of array and weights must match/);
expect(function () {
chance.weighted(['a', 'b', 'c', 'd'], [1, 2, 3, 4]);
}).to.not.throw(RangeError, /length of array and weights must match/);
expect(function () {
chance.weighted(['a', 'b', 'c', 'd'], [1, 2, 3, 4, 5]);
}).to.throw(RangeError, /length of array and weights must match/);
});
it("returns with results properly weighted", function() {
// Use Math.random as the random function rather than our Mersenne twister just to
// speed things up here because this test takes awhile to gather enough data to
// have a large enough sample size to adequately test. This increases performance
// by a few orders of magnitude
var chance = new Chance(Math.random);
_(10).times(function() {
var picked = { a: 0, b: 0, c: 0, d: 0 };
// This makes it a tad slow, but we need a large enough sample size to adequately test
_(50000).times(function () {
picked[chance.weighted(['a', 'b', 'c', 'd'], [1, 100, 100, 1])]++;
});
// This range is somewhat arbitrary, but good enough to test our constraints
expect(picked.b / picked.a).to.be.within(60, 140);
expect(picked.c / picked.d).to.be.within(60, 140);
expect((picked.c / picked.b) * 100).to.be.within(50, 150);
});
});
it("works with fractional weights", function() {
// Use Math.random as the random function rather than our Mersenne twister just to
// speed things up here because this test takes awhile to gather enough data to
// have a large enough sample size to adequately test. This increases performance
// by a few orders of magnitude
var chance = new Chance(Math.random);
_(10).times(function() {
var picked = { a: 0, b: 0, c: 0, d: 0 };
// This makes it a tad slow, but we need a large enough sample size to adequately test
_(50000).times(function () {
picked[chance.weighted(['a', 'b', 'c', 'd'], [0.001, 0.1, 0.1, 0.001])]++;
});
// This range is somewhat arbitrary, but good enough to test our constraints
expect(picked.b / picked.a).to.be.within(60, 140);
expect(picked.c / picked.d).to.be.within(60, 140);
expect((picked.c / picked.b) * 100).to.be.within(50, 150);
});
});
it("works with weights of 0", function () {
picked = chance.weighted(['a', 'b', 'c'], [1, 0, 1]);
expect(picked).to.be.a('string');
});
it("works with negative weights", function () {
picked = chance.weighted(['a', 'b', 'c'], [1, -2, 1]);
expect(picked).to.be.a('string');
});
});
describe("shuffle()", function () {
it("returns an array of the same size", function () {
arr = ['a', 'b', 'c', 'd', 'e'];
_(1000).times(function () {
expect(chance.shuffle(_.clone(arr))).to.have.length(5);
expect(chance.shuffle(_.clone(arr))).to.contain('a');
var arr2 = _.clone(arr);
chance.shuffle(arr2);
expect(arr2).to.not.be.empty;
});
});
it("returns a well shuffled array", function () {
// See http://vq.io/1lEhbim checking it isn't doing that!
arr = ['a', 'b', 'c', 'd', 'e'];
var positions = {
a: [0, 0, 0, 0, 0],
b: [0, 0, 0, 0, 0],
c: [0, 0, 0, 0, 0],
d: [0, 0, 0, 0, 0],
e: [0, 0, 0, 0, 0]
};
_(10000).times(function () {
arr = chance.shuffle(arr);
// Accumulate the position of the a each time
arr.forEach(function(item, index) {
positions[item][index]++;
});
});
// Divide by the estimated number of a's which should appear in each
// position
_.forEach(positions, function(position, index) {
positions[index] = _.map(position, function(item) {
return item/10000;
});
});
_.forEach(positions, function(position) {
_.forEach(position, function(item) {
// This should be around 20% give or take a bit since there are
// 5 elements and they should be evenly distributed
expect(item).to.be.within(0.18, 0.22);
});
});
});
});
describe("unique", function () {
it("gives a unique array of the selected function", function () {
_(500).times(function () {
var arr = chance.unique(chance.character, 25, {pool: "abcdefghijklmnopqrstuvwxyz"});
expect(arr).to.be.an('array');
expect(_.uniq(arr).length).to.equal(25);
});
});
it("throws a RangeError when num is likely out of range", function () {
expect(function () {
chance.unique(chance.character, 10, {pool: 'abcde'});
}).to.throw(RangeError, /too large/);
});
it("throws a RangeError when first argument is not a function", function () {
expect(function () {
chance.unique(chance.character({pool: 'abcde'}), 10);
}).to.throw(RangeError, /first argument must be a function/);
});
it("will take a custom comparator for comparing complex objects", function () {
_(1000).times(function () {
var arr = chance.unique(chance.currency, 25, {
comparator: function(arr, val) {
// If this is the first element, we know it doesn't exist
if (arr.length === 0) {
return false;
}
return arr.reduce(function(acc, item) {
// If a match has been found, short circuit check and just return
if (acc) {
return acc;
}
return item.name === val.name;
}, false);
}
});
expect(_.uniq(arr).length).to.equal(25);
});
});
});
describe("n random terms", function () {
it("gives an array of n terms for the given function", function () {
var arr = chance.n(chance.email, 25, {domain: "example.com"});
expect(arr).to.be.an('array');
expect(arr[0]).to.match(/example\.com$/);
expect(arr.length).to.equal(25);
});
it("gives an array of 1 term when n is not given", function () {
var arr = chance.n(chance.email);
expect(arr).to.be.an('array');
expect(arr.length).to.equal(1);
});
it("throws a RangeError when first argument is not a function", function () {
expect(function () {
chance.n(chance.character({pool: 'abcde'}), 10);
}).to.throw(RangeError, /first argument must be a function/);
});
it("gives an empty array when n is set to 0", function () {
var arr = chance.n(chance.email, 0);
expect(arr).to.be.an('array');
expect(arr.length).to.equal(0);
});
});
describe("pad()", function () {
it("always returns same number when width same as the length of the number", function () {
_(1000).times(function () {
var num = chance.natural({min: 10000, max: 99999});
expect(chance.pad(num, 5)).to.be.a('string');
expect(chance.pad(num, 5)).to.have.length(5);
});
});
it("will pad a smaller number to the right width", function () {
_(1000).times(function () {
var num = chance.natural({max: 99999});
expect(chance.pad(num, 10)).to.be.a('string');
expect(chance.pad(num, 10)).to.have.length(10);
expect(chance.pad(num, 10).indexOf('00000')).to.not.equal(-1);
});
});
it("can specify pad element", function () {
_(1000).times(function () {
var num = chance.natural({max: 99999});
expect(chance.pad(num, 10, 'V')).to.be.a('string');
expect(chance.pad(num, 10, 'V')).to.have.length(10);
expect(chance.pad(num, 10, 'V').indexOf('VVVVV')).to.not.equal(-1);
});
});
});
});