1 | import test from 'ava'
|
2 | import Chance from '../chance.js'
|
3 | import _ from 'lodash'
|
4 |
|
5 | const chance = new Chance()
|
6 |
|
7 | const timeout = (seconds) => {
|
8 | new Promise((resolve, reject) => {
|
9 | setTimeout(() => resolve(), seconds)
|
10 | })
|
11 | }
|
12 |
|
13 | test('bool() returns a random boolean', t => {
|
14 | let bool = chance.bool()
|
15 | t.is(typeof bool, 'boolean')
|
16 | })
|
17 |
|
18 | test('bool() is within the bounds of what we would call random', t => {
|
19 | let trueCount = 0;
|
20 | _.times(1000, () => {
|
21 | if (chance.bool()) {
|
22 | trueCount++
|
23 | }
|
24 | })
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | t.true((trueCount > 200) && (trueCount < 800))
|
31 | })
|
32 |
|
33 | test('bool() takes and obeys likelihood', t => {
|
34 | let trueCount = 0
|
35 | _.times(1000, () => {
|
36 | if (chance.bool({ likelihood: 30 })) {
|
37 | trueCount++
|
38 | }
|
39 | })
|
40 |
|
41 |
|
42 | t.true((trueCount > 200) && (trueCount < 400))
|
43 |
|
44 | trueCount = 0
|
45 | _.times(1000, () => {
|
46 | if (chance.bool({ likelihood: 99 })) {
|
47 | trueCount++
|
48 | }
|
49 | })
|
50 |
|
51 |
|
52 | t.true(trueCount > 900)
|
53 | })
|
54 |
|
55 | test('bool() throws an error if likelihood < 0 or > 100', t => {
|
56 | const fn1 = () => chance.bool({likelihood: -23})
|
57 | t.throws(fn1, RangeError)
|
58 | const fn2 = () => chance.bool({likelihood: 7933})
|
59 | t.throws(fn2, RangeError)
|
60 | })
|
61 |
|
62 | test('Chance() null works', async t => {
|
63 | t.plan(1)
|
64 |
|
65 | let chance1 = Chance(null)
|
66 |
|
67 |
|
68 | await timeout(5)
|
69 | let chance2 = Chance(null)
|
70 | t.not(chance1.random(), chance2.random())
|
71 | })
|
72 |
|
73 | test('Chance() does return differing results if differing seeds provided', t => {
|
74 | let chance1 = new Chance(12345)
|
75 | let chance2 = new Chance(54321)
|
76 | t.not(chance1.random(), chance2.random())
|
77 | })
|
78 |
|
79 | test('Chance() does not return repeatable results if no seed provided', async t => {
|
80 | t.plan(1000)
|
81 | let chance1 = new Chance()
|
82 | await timeout(5)
|
83 | let chance2 = new Chance()
|
84 | _.times(1000, () => {
|
85 | t.not(chance1.random(), chance2.random())
|
86 | })
|
87 | })
|
88 |
|
89 | test('Chance() returns repeatable results if seed provided on the Chance object', t => {
|
90 | let seed = new Date().getTime()
|
91 | let chance1 = new Chance(seed)
|
92 | let chance2 = new Chance(seed)
|
93 |
|
94 | _.times(1000, () => {
|
95 | t.is(chance1.random(), chance2.random())
|
96 | })
|
97 | })
|
98 |
|
99 | test('Chance() returns repeatable results if a string is provided as a seed', t => {
|
100 | let seed = "foo"
|
101 | let chance1 = new Chance(seed)
|
102 | let chance2 = new Chance(seed)
|
103 |
|
104 | _.times(1000, () => {
|
105 | t.is(chance1.random(), chance2.random())
|
106 | })
|
107 | })
|
108 |
|
109 | test('Chance() returns different results if two different strings are provided', t => {
|
110 | let chance1 = new Chance("foo")
|
111 | let chance2 = new Chance("baz")
|
112 |
|
113 | _.times(1000, () => {
|
114 | t.not(chance1.random(), chance2.random())
|
115 | })
|
116 | })
|
117 |
|
118 | test('Chance() returns different results if two different strings are provided redux', t => {
|
119 |
|
120 | let chance1 = new Chance("abe")
|
121 | let chance2 = new Chance("acc")
|
122 |
|
123 | _.times(1000, () => {
|
124 | t.not(chance1.random(), chance2.random())
|
125 | })
|
126 | })
|
127 |
|
128 | test('Chance() returns different results if multiple arguments are provided', t => {
|
129 | let seed = new Date().getTime()
|
130 | let chance1 = new Chance(seed, "foo")
|
131 | let chance2 = new Chance(seed, "bar")
|
132 |
|
133 | _.times(1000, () => {
|
134 | t.not(chance1.random(), chance2.random())
|
135 | })
|
136 | })
|
137 |
|
138 | test('Chance() will take an arbitrary function for the seed and use it', t => {
|
139 | let chance = new Chance(() => 123)
|
140 |
|
141 | _.times(1000, () => {
|
142 | t.is(chance.random(), 123)
|
143 | })
|
144 | })
|
145 |
|
146 | test('character() returns a character', t => {
|
147 | let char = chance.character()
|
148 | t.is(typeof char, 'string')
|
149 | t.is(char.length, 1)
|
150 | })
|
151 |
|
152 | test('character() pulls only from pool, when specified', t => {
|
153 | _.times(1000, () => {
|
154 | let char = chance.character({ pool: 'abcde' })
|
155 | t.true(/[abcde]/.test(char))
|
156 | })
|
157 | })
|
158 |
|
159 | test('character() allows only alpha', t => {
|
160 | _.times(1000, () => {
|
161 | let char = chance.character({ alpha: true })
|
162 | t.true(/[a-zA-Z]/.test(char))
|
163 | })
|
164 | })
|
165 |
|
166 | test('character() throws when specifying both alpha and symbols', t => {
|
167 | const fn = () => chance.character({alpha: true, symbols: true})
|
168 | t.throws(fn, 'Chance: Cannot specify both alpha and symbols.')
|
169 | })
|
170 |
|
171 | test('character() obeys upper case', t => {
|
172 | _.times(1000, () => {
|
173 | let char = chance.character({ alpha: true, casing: 'upper' })
|
174 | t.true(/[A-Z]/.test(char))
|
175 | })
|
176 | })
|
177 |
|
178 | test('character() obeys lower case', t => {
|
179 | _.times(1000, () => {
|
180 | let char = chance.character({ alpha: true, casing: 'lower' })
|
181 | t.true(/[a-z]/.test(char))
|
182 | })
|
183 | })
|
184 |
|
185 | test('floating() returns a random floating', t => {
|
186 | t.is(typeof chance.floating(), 'number')
|
187 | })
|
188 |
|
189 | test('floating() can take both a max and min and obey them both', t => {
|
190 | _.times(1000, () => {
|
191 | let floating = chance.floating({ min: 90, max: 100 })
|
192 | t.true(floating > 89)
|
193 | t.true(floating < 101)
|
194 | })
|
195 | })
|
196 |
|
197 | test('floating() will not take fixed + min that would be out of range', t => {
|
198 | const fn = () => chance.floating({ fixed: 13, min: -9007199254740992 })
|
199 | t.throws(fn, "Chance: Min specified is out of range with fixed. Min should be, at least, -900.7199254740992")
|
200 | })
|
201 |
|
202 | test('floating() will not take fixed + max that would be out of range', t => {
|
203 | const fn = () => chance.floating({ fixed: 13, max: 9007199254740992 })
|
204 | t.throws(fn, "Chance: Max specified is out of range with fixed. Max should be, at most, 900.7199254740992")
|
205 | })
|
206 |
|
207 | test('floating() obeys the fixed parameter, when present', t => {
|
208 | _.times(1000, () => {
|
209 | let floating = chance.floating({ fixed: 4 })
|
210 | let decimals = floating.toString().split('.')[1] ? floating.toString().split('.')[1] : ''
|
211 | t.true(decimals.length < 5)
|
212 | })
|
213 | })
|
214 |
|
215 | test('floating() can take fixed and obey it', t => {
|
216 | _.times(1000, () => {
|
217 | let floating = chance.floating({ fixed: 3 })
|
218 | let parsed = parseFloat(floating.toFixed(3))
|
219 | t.is(floating, parsed)
|
220 | })
|
221 | })
|
222 |
|
223 | test('floating() will not take both fixed and precision', t => {
|
224 | const fn = () => chance.floating({fixed: 2, precision: 8})
|
225 | t.throws(fn, 'Chance: Cannot specify both fixed and precision.')
|
226 | })
|
227 |
|
228 | test('get() works as expected', t => {
|
229 | let data = chance.get('lastNames')
|
230 | t.true(typeof data === 'object')
|
231 | })
|
232 |
|
233 | test('hex() works as expected', t => {
|
234 | _.times(1000, () => {
|
235 | t.true(/[0-9a-f]/.test(chance.hex()))
|
236 | })
|
237 | })
|
238 |
|
239 | test('hex() can take Upper and obey it', t => {
|
240 | _.times(1000, () => {
|
241 | t.true(/[0-9A-F]/.test(chance.hex({ casing: 'upper' })))
|
242 | })
|
243 | })
|
244 |
|
245 | test('integer() returns a random integer', t => {
|
246 | t.is(typeof chance.integer(), 'number')
|
247 | })
|
248 |
|
249 | test('integer() is sometimes negative, sometimes positive', t => {
|
250 | let positiveCount = 0
|
251 | _.times(1000, () => {
|
252 | if (chance.integer() > 0) {
|
253 | positiveCount++
|
254 | }
|
255 | })
|
256 |
|
257 |
|
258 |
|
259 |
|
260 | t.true((positiveCount > 200) && (positiveCount < 800))
|
261 | })
|
262 |
|
263 | test('integer() can take a zero min and obey it', t => {
|
264 | _.times(1000, () => {
|
265 | t.true(chance.integer({ min: 0 }) > 0)
|
266 | })
|
267 | })
|
268 |
|
269 | test('integer() can take a negative min and obey it', t => {
|
270 | _.times(1000, () => {
|
271 | t.true(chance.integer({ min: -25 }) > -26)
|
272 | })
|
273 | })
|
274 |
|
275 | test('integer() can take a negative min and max and obey both', t => {
|
276 | _.times(1000, () => {
|
277 | let integer = chance.integer({ min: -25, max: -1 })
|
278 | t.true((integer > -26) && integer < 0)
|
279 | })
|
280 | })
|
281 |
|
282 | test('integer() can take a min with absolute value less than max and return in range above', t => {
|
283 | let count = 0
|
284 | _.times(1000, () => {
|
285 |
|
286 |
|
287 | if (Math.abs(chance.integer({ min: -1, max: 1000000 })) < 2) {
|
288 | count++
|
289 | }
|
290 | })
|
291 | t.true(count < 900)
|
292 | })
|
293 |
|
294 | test('integer() throws an error when min > max', t => {
|
295 | const fn = () => chance.integer({ min: 1000, max: 500 })
|
296 | t.throws(fn, 'Chance: Min cannot be greater than Max.')
|
297 | })
|
298 |
|
299 | test('letter() returns a letter', t => {
|
300 | _.times(1000, () => {
|
301 | let letter = chance.letter()
|
302 | t.is(typeof letter, 'string')
|
303 | t.is(letter.length, 1)
|
304 | t.true(letter.match(/[a-z]/) !== null)
|
305 | })
|
306 | })
|
307 |
|
308 | test('letter() can take upper case', t => {
|
309 | _.times(1000, () => {
|
310 | let letter = chance.letter({ casing: 'upper' })
|
311 | t.is(typeof letter, 'string')
|
312 | t.is(letter.length, 1)
|
313 | t.true(letter.match(/[A-Z]/) !== null)
|
314 | })
|
315 | })
|
316 |
|
317 | test('natural() returns a random natural', t => {
|
318 | t.is(typeof chance.natural(), 'number')
|
319 | })
|
320 |
|
321 | test('natural() throws an error if min < 0', t => {
|
322 | const fn = () => chance.natural({ min: -23 })
|
323 | t.throws(fn, 'Chance: Min cannot be less than zero.')
|
324 | })
|
325 |
|
326 | test('natural() is always positive or zero', t => {
|
327 | let positiveCount = 0
|
328 | _.times(1000, () => {
|
329 | if (chance.natural() >= 0) {
|
330 | positiveCount++
|
331 | }
|
332 | })
|
333 | t.is(positiveCount, 1000)
|
334 | })
|
335 |
|
336 | test('natural() can take just a min and obey it', t => {
|
337 | _.times(1000, () => {
|
338 | t.true(chance.natural({ min: 9007199254740991 }) > 9007199254740990)
|
339 | })
|
340 | })
|
341 |
|
342 | test('natural() can take just a max and obey it', t => {
|
343 | _.times(1000, () => {
|
344 | t.true(chance.natural({ max: 100 }) < 101)
|
345 | })
|
346 | })
|
347 |
|
348 | test('natural() can take both a max and min and obey them both', t => {
|
349 | _.times(1000, () => {
|
350 | let natural = chance.natural({ min: 90, max: 100 })
|
351 | t.true(natural > 89)
|
352 | t.true(natural < 101)
|
353 | })
|
354 | })
|
355 |
|
356 | test('natural() works with both bounds 0', t => {
|
357 | _.times(1000, () => {
|
358 | t.is(chance.natural({ min: 0, max: 0 }), 0)
|
359 | })
|
360 | })
|
361 |
|
362 | test('natural() respects numerals', t => {
|
363 | _.times(1000, () => {
|
364 | let natural = chance.natural({ numerals: 2 })
|
365 | t.true(natural <= 99)
|
366 | t.true(natural >= 10)
|
367 | })
|
368 | })
|
369 |
|
370 | test('natural() throws an error if min > max', t => {
|
371 | const fn = () => chance.natural({ min: 1000, max: 500 })
|
372 | t.throws(fn, 'Chance: Min cannot be greater than Max.')
|
373 | })
|
374 |
|
375 | test('natural() throws an error if numerals is less than 1', t => {
|
376 | const fn = () => chance.natural({ numerals: 0 })
|
377 | t.throws(fn, 'Chance: Numerals cannot be less than one.')
|
378 | })
|
379 |
|
380 | test('set() works as expected', t => {
|
381 | let cData = { lastNames: ['customName', 'testLast'] }
|
382 | chance.set(cData)
|
383 | let data = chance.get('lastNames')
|
384 | t.true(_.isArray(data))
|
385 | t.is(data.length, 2)
|
386 | })
|
387 |
|
388 | test('string() returns a string', t => {
|
389 | t.is(typeof chance.string(), 'string')
|
390 | })
|
391 |
|
392 | test('string() obeys length, when specified', t => {
|
393 | _.times(1000, () => {
|
394 | let length = chance.natural({ min: 1, max: 25 })
|
395 | t.is(chance.string({ length: length }).length, length)
|
396 | })
|
397 | })
|
398 |
|
399 | test('string() throws error if length < 0', t => {
|
400 | const fn = () => chance.string({ length: -23 })
|
401 | t.throws(fn, 'Chance: Length cannot be less than zero.')
|
402 | })
|
403 |
|
404 | test('string() returns only letters with alpha', t => {
|
405 | _.times(1000, () => {
|
406 | let str = chance.string({ alpha: true })
|
407 | t.true(/[a-zA-Z]+/.test(str))
|
408 | })
|
409 | })
|
410 |
|
411 | test('string() obeys upper case', t => {
|
412 | _.times(1000, () => {
|
413 | let str = chance.string({ alpha: true, casing: 'upper' })
|
414 | t.true(/[A-Z]+/.test(str))
|
415 | })
|
416 | })
|
417 |
|
418 | test('string() obeys lower case', t => {
|
419 | _.times(1000, () => {
|
420 | let str = chance.string({ alpha: true, casing: 'lower' })
|
421 | t.true(/[a-z]+/.test(str))
|
422 | })
|
423 | })
|
424 |
|
425 | test('string() obeys symbol', t => {
|
426 | _.times(1000, () => {
|
427 | let str = chance.string({ symbols: true })
|
428 | t.true(/[\!\@\#\$\%\^\&\*\(\)\[\]]+/.test(str))
|
429 | })
|
430 | })
|