diff options
author | Minteck <contact@minteck.org> | 2021-12-21 16:52:28 +0100 |
---|---|---|
committer | Minteck <contact@minteck.org> | 2021-12-21 16:52:28 +0100 |
commit | 46e43f4bde4a35785b4997b81e86cd19f046b69b (patch) | |
tree | c53c2f826f777f9d6b2d249dab556feb72a6c3a6 /src/node_modules/chance/test/test.helpers.js | |
download | langdetect-46e43f4bde4a35785b4997b81e86cd19f046b69b.tar.gz langdetect-46e43f4bde4a35785b4997b81e86cd19f046b69b.tar.bz2 langdetect-46e43f4bde4a35785b4997b81e86cd19f046b69b.zip |
Commit
Diffstat (limited to 'src/node_modules/chance/test/test.helpers.js')
-rw-r--r-- | src/node_modules/chance/test/test.helpers.js | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/src/node_modules/chance/test/test.helpers.js b/src/node_modules/chance/test/test.helpers.js new file mode 100644 index 0000000..171bcc2 --- /dev/null +++ b/src/node_modules/chance/test/test.helpers.js @@ -0,0 +1,433 @@ +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) + }) +}) |