Current File : //home/tradevaly/www/node_modules/chance/test/test.helpers.js |
import test from 'ava'
import Chance from '../chance.js'
import _ from 'lodash'
const chance = new Chance()
// chance.capitalize()
test('capitalize() works as expected', t => {
_.times(1000, () => {
let word = chance.capitalize(chance.word())
t.true(_.isString(word))
t.true(/[A-Z]/.test(word))
})
})
// chance.n()
test('n() gives an array of n terms for the given function', t => {
let arr = chance.n(chance.email, 25, { domain: 'example.com' })
t.true(_.isArray(arr))
t.is(arr.length, 25)
arr.map((email) => {
t.true(/example\.com$/.test(email))
})
})
test('n() gives an array of 1 when n not given', t => {
let arr = chance.n(chance.email)
t.true(_.isArray(arr))
t.is(arr.length, 1)
})
test('n() throws when first argument is not a function', t => {
let testFns = [
() => chance.n(chance.character({ pool: 'abcde' }), 10),
() => chance.n('foo', 10),
() => chance.n({}, 10),
() => chance.n(null, 10),
() => chance.n(undefined, 10),
() => chance.n(21, 10),
]
testFns.map((fn) => {
t.throws(fn, 'Chance: The first argument must be a function.')
})
})
test('n() gives an empty array when n is set to 0', t => {
let arr = chance.n(chance.email, 0)
t.true(_.isArray(arr))
t.is(arr.length, 0)
})
// chance.pick()
test('pick() returns a single element when called without a count argument', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pick(arr)
t.is(picked.length, 1)
})
})
test('pick() returns a multiple elements when called with a count argument', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pick(arr, 3)
t.is(picked.length, 3)
})
})
test('pick() does not destroy the original array', t => {
let arr = ['a', 'b', 'c', 'd', 'e', 'f'];
_.times(1000, () => {
let cloned = _.clone(arr)
let picked = chance.pick(cloned, 3)
t.is(cloned.length, 6)
t.deepEqual(arr, cloned)
})
})
test('pick() throws if zero elements in array', t => {
const fn = () => chance.pick([])
t.throws(fn, 'Chance: Cannot pick() from an empty array')
})
// chance.pickone()
test('pickone() returns a single element', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pickone(arr)
t.is(picked.length, 1)
t.false(_.isArray(picked))
})
})
test('pickone() throws if zero elements in array', t => {
const fn = () => chance.pickone([])
t.throws(fn, 'Chance: Cannot pickone() from an empty array')
})
// chance.pickset()
test('pickset() returns empty array when count 0', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pickset(arr, 0)
t.is(picked.length, 0)
t.true(_.isArray(picked))
})
})
test('pickset() throws if zero elements in array', t => {
const fn = () => chance.pickset([])
t.throws(fn, 'Chance: Cannot pickset() from an empty array')
})
test('pickset() returns single element array if no count provided', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pickset(arr)
t.is(picked.length, 1)
t.true(_.isArray(picked))
})
})
test('pickset() throws if count is not positive number', t => {
let arr = ['a', 'b', 'c', 'd']
const fn = () => chance.pickset(arr, -1)
t.throws(fn, 'Chance: Count must be a positive number')
})
test('pickset() returns single element array when called with count of 1', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pickset(arr, 1)
t.is(picked.length, 1)
t.true(_.isArray(picked))
})
})
test('pickset() returns multiple elements when called with count > 1', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pickset(arr, 3)
t.is(picked.length, 3)
t.true(_.isArray(picked))
})
})
test('pickset() returns no more values than the size of the array', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pickset(arr, 5)
t.is(picked.length, 4)
})
})
test('pickset() does not destroy the original array', t => {
let arr = ['a', 'b', 'c', 'd', 'e', 'f'];
_.times(1000, () => {
let cloned = _.clone(arr)
let picked = chance.pickset(cloned, 3)
t.is(cloned.length, 6)
t.deepEqual(arr, cloned)
})
})
test('pickset() returns unique values', t => {
let arr = ['a', 'b', 'c', 'd']
_.times(1000, () => {
let picked = chance.pickset(arr, 4)
t.not(picked.indexOf('a'), -1)
t.not(picked.indexOf('b'), -1)
t.not(picked.indexOf('c'), -1)
t.not(picked.indexOf('d'), -1)
})
})
// chance.shuffle()
test('shuffle() returns an array of the same size', t => {
let arr = ['a', 'b', 'c', 'd', 'e']
_.times(1000, () => {
let shuffled = chance.shuffle(_.clone(arr))
t.is(shuffled.length, 5)
t.not(shuffled.indexOf('a'), -1)
})
})
test('shuffle() returns a well shuffled array', t => {
// See http://vq.io/1lEhbim checking it isn't doing that!
let arr = ['a', 'b', 'c', 'd', 'e'];
let 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]
};
let shuffled = _.clone(arr)
_.times(10000, () => {
shuffled = chance.shuffle(shuffled)
shuffled.map((item, index) => {
// Accumulate the position of the item each time
positions[item][index]++
})
})
Object.keys(positions).map((index) => {
let position = positions[index]
position.map((item) => {
// This should be around 20% give or take a bit since there are
// 5 elements and they should be evenly distributed
t.true(item >= 1800)
t.true(item <= 2200)
})
})
})
test('shuffle() does not destroy original array', t => {
let arr = ['a', 'b', 'c', 'd', 'e']
_.times(1000, () => {
let cloned = _.clone(arr)
let shuffled = chance.shuffle(cloned)
t.is(shuffled.length, 5)
t.deepEqual(arr, cloned)
})
})
// chance.unique()
test('unique() gives a unique array of the selected function', t => {
_.times(500, () => {
let arr = chance.unique(chance.character, 25, { pool: "abcdefghijklmnopqrstuvwxyz" })
t.true(_.isArray(arr))
t.is(_.uniq(arr).length, 25)
})
})
test('unique() works properly with options', t => {
_.times(500, () => {
let arr = chance.unique(chance.date, 20, { year: 2016 })
t.true(_.isArray(arr))
t.is(_.uniq(arr).length, 20)
})
})
test('unique() throws when num is likely out of range', t => {
const fn = () => chance.unique(chance.character, 10, { pool: 'abcde' })
t.throws(fn, 'Chance: num is likely too large for sample set')
})
test('unique() throws when first argument is not a function', t => {
const fn = () => chance.unique(chance.character({ pool: 'abcde' }), 10)
t.throws(fn, 'Chance: The first argument must be a function.')
})
test('unique() will take a custom comparator for comparing complex objects', t => {
const comparator = (arr, val) => {
// If this is the first element, we know it doesn't exist
if (arr.length === 0) {
return false
} else {
// If a match has been found, short circuit check and just return
return arr.reduce((acc, item) => acc ? acc : item.name === val.name, false)
}
}
let arr = chance.unique(chance.currency, 25, { comparator: comparator })
t.is(_.uniq(arr).length, 25)
})
test('unique() works without a third argument', t => {
_.times(200, () => {
t.true(_.isArray(chance.unique(chance.character, 10)))
})
})
// chance.weighted()
test('weighted() returns an element', t => {
_.times(1000, () => {
let picked = chance.weighted(['a', 'b', 'c', 'd'], [1, 1, 1, 1])
t.true(_.isString(picked))
t.is(picked.length, 1)
})
})
test('weighted() works with just 2 items', t => {
// Use Math.random as the random function rather than our Mersenne twister
// just tospeed 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)
let 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
_.times(50000, () => {
picked[chance.weighted(['a', 'b'], [1, 100])]++
})
// This range is somewhat arbitrary, but good enough to test our constraints
let ratio = picked.b / picked.a
t.true(ratio > 80)
t.true(ratio < 120)
})
test('weighted() works with trim', t => {
_.times(1000, () => {
let picked = chance.weighted(['a', 'b', 'c', 'd'], [1, 1, 1, 1], true)
t.true(_.isString(picked))
t.is(picked.length, 1)
})
})
test('weighted() throws error if called with an array of weights different from options', t => {
const fn = () => chance.weighted(['a', 'b', 'c', 'd'], [1, 2, 3])
t.throws(fn, 'Chance: Length of array and weights must match')
})
test('weighted() does not throw error if called with good weights', t => {
const fn = () => chance.weighted(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
t.notThrows(fn)
})
test('weighted() throws error if weights invalid', t => {
const fn = () => chance.weighted(['a', 'b', 'c', 'd'], [0, 0, 0, 0])
t.throws(fn, 'Chance: No valid entries in array weights')
})
test('weighted() throws error if called with an array of weights different from options 2', t => {
const fn = () => chance.weighted(['a', 'b', 'c', 'd'], [1, 2, 3, 4, 5])
t.throws(fn, 'Chance: Length of array and weights must match')
})
test('weighted() throws error if weights contains NaN', t => {
const fn = () => chance.weighted(['a', 'b', 'c', 'd'], [1, NaN, 1, 1])
t.throws(fn, 'Chance: All weights must be numbers')
})
test('weighted() returns results properly weighted', t => {
// Use Math.random as the random function rather than our Mersenne twister
// just tospeed 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)
let chance = new Chance(Math.random)
let picked = { a: 0, b: 0, c: 0, d: 0 }
_.times(50000, () => {
picked[chance.weighted(['a', 'b', 'c', 'd'], [1, 100, 100, 1])]++
})
// This range is somewhat arbitrary, but good enough to test our constraints
let baRatio = picked.b / picked.a
t.true(baRatio > 60)
t.true(baRatio < 140)
let cdRatio = picked.c / picked.d
t.true(cdRatio > 60)
t.true(cdRatio < 140)
let cbRatio = (picked.c / picked.b) * 100
t.true(cbRatio > 50)
t.true(cbRatio < 150)
})
test('weighted() works with fractional weights', t => {
// Use Math.random as the random function rather than our Mersenne twister
// just tospeed 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)
let chance = new Chance(Math.random)
let picked = { a: 0, b: 0, c: 0, d: 0 }
_.times(50000, () => {
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
let baRatio = picked.b / picked.a
t.true(baRatio > 60)
t.true(baRatio < 140)
let cdRatio = picked.c / picked.d
t.true(cdRatio > 60)
t.true(cdRatio < 140)
let cbRatio = (picked.c / picked.b) * 100
t.true(cbRatio > 50)
t.true(cbRatio < 150)
})
test('weighted() works with weight of 0', t => {
_.times(1000, () => {
let picked = chance.weighted(['a', 'b', 'c'], [1, 0, 1])
t.true(_.isString(picked))
t.true(picked !== 'b')
})
})
test('weighted() works with negative weight', t => {
_.times(1000, () => {
let picked = chance.weighted(['a', 'b', 'c'], [1, -2, 1])
t.true(_.isString(picked))
t.true(picked !== 'b')
})
})
// chance.pad()
test('pad() always returns same number when width same as length of number', t => {
_.times(1000, () => {
let num = chance.natural({ min: 10000, max: 99999 })
let padded = chance.pad(num, 5)
t.true(_.isString(padded))
t.is(padded.length, 5)
})
})
test('pad() will pad smaller number to the right width', t => {
_.times(1000, () => {
let num = chance.natural({ max: 99999 })
let padded = chance.pad(num, 10)
t.true(_.isString(padded))
t.is(padded.length, 10)
t.not(padded.indexOf('00000'), -1)
})
})
test('pad() can take a pad e.lement', t => {
_.times(1000, () => {
let num = chance.natural({ max: 99999 })
let padded = chance.pad(num, 10, 'V')
t.true(_.isString(padded))
t.is(padded.length, 10)
t.not(padded.indexOf('VVVVV'), -1)
})
})