Skip to content

Commit 46bf568

Browse files
Shinigami92ST-DDT
andcommitted
feat: reimplement datatype.bigInt
Co-authored-by: ST-DDT <[email protected]>
1 parent c3250c3 commit 46bf568

File tree

2 files changed

+139
-17
lines changed

2 files changed

+139
-17
lines changed

src/modules/datatype/index.ts

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -261,20 +261,59 @@ export class Datatype {
261261
/**
262262
* Returns a [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#bigint_type) number.
263263
*
264-
* @param value When provided, this method simply converts it to `BigInt` type.
264+
* @param options Maximum value or options object.
265+
* @param options.min Lower bound for generated bigint. Defaults to `0n`.
266+
* @param options.max Upper bound for generated bigint. Defaults to `min + 999999999999999n`.
267+
*
268+
* @throws When options define `max < min`.
265269
*
266270
* @example
267-
* faker.datatype.bigInt() // 8507209999914928n
268-
* faker.datatype.bigInt('156') // 156n
269-
* faker.datatype.bigInt(30) // 30n
270-
* faker.datatype.bigInt(3000n) // 3000n
271-
* faker.datatype.bigInt(true) // 1n
271+
* faker.datatype.bigInt() // 55422n
272+
* faker.datatype.bigInt(100n) // 52n
273+
* faker.datatype.bigInt({ min: 1000000n }) // 431433n
274+
* faker.datatype.bigInt({ max: 100n }) // 42n
275+
* faker.datatype.bigInt({ min: 10n, max: 100n }) // 36n
272276
*/
273-
bigInt(value?: string | number | bigint | boolean): bigint {
274-
if (value === undefined) {
275-
value = Math.floor(this.number() * 99999999999) + 10000000000;
277+
bigInt(
278+
options?:
279+
| bigint
280+
| boolean
281+
| number
282+
| string
283+
| {
284+
min?: bigint | boolean | number | string;
285+
max?: bigint | boolean | number | string;
286+
}
287+
): bigint {
288+
let min: bigint;
289+
let max: bigint;
290+
291+
if (typeof options === 'object') {
292+
min = BigInt(options.min ?? 0);
293+
max = BigInt(options.max ?? min + BigInt(999999999999999));
294+
} else {
295+
min = BigInt(0);
296+
max = BigInt(options ?? 999999999999999);
276297
}
277298

278-
return BigInt(value);
299+
if (max === min) {
300+
return min;
301+
}
302+
303+
if (max < min) {
304+
throw new FakerError(`Max ${max} should be larger then min ${min}.`);
305+
}
306+
307+
const delta = max - min;
308+
309+
const offset =
310+
BigInt(
311+
this.faker.random.numeric(delta.toString(10).length, {
312+
allowLeadingZeros: true,
313+
})
314+
) %
315+
(delta + BigInt(1));
316+
317+
return min + offset;
279318
}
280319
}

test/datatype.spec.ts

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from 'vitest';
2-
import { faker } from '../src';
2+
import { faker, FakerError } from '../src';
33

44
const seededRuns = [
55
{
@@ -69,8 +69,8 @@ const seededRuns = [
6969
length: [79654, '2eiXX/J/*&', 86617, 60111],
7070
},
7171
bigInt: {
72-
noArgs: 3745409999962546n,
73-
value: 42n,
72+
noArgs: 379177551410048n,
73+
value: 37n,
7474
},
7575
},
7676
},
@@ -141,8 +141,8 @@ const seededRuns = [
141141
length: [56052, 21258, 54308, 3397],
142142
},
143143
bigInt: {
144-
noArgs: 2620209999973798n,
145-
value: 42n,
144+
noArgs: 251225403255239n,
145+
value: 25n,
146146
},
147147
},
148148
},
@@ -213,8 +213,8 @@ const seededRuns = [
213213
length: ['Kti5-}$_/`', 76408, 35403, 69406],
214214
},
215215
bigInt: {
216-
noArgs: 9285209999907148n,
217-
value: 42n,
216+
noArgs: 948721906162743n,
217+
value: 8n,
218218
},
219219
},
220220
},
@@ -417,6 +417,19 @@ describe('datatype', () => {
417417
const actual = faker.datatype.bigInt(42);
418418
expect(actual).toEqual(expectations.bigInt.value);
419419
});
420+
421+
it('should throw when min > max', () => {
422+
const min = 10000n;
423+
const max = 999n;
424+
425+
faker.seed(seed);
426+
427+
expect(() => {
428+
faker.datatype.bigInt({ min, max });
429+
}).toThrowError(
430+
new FakerError(`Max ${max} should be larger then min ${min}.`)
431+
);
432+
});
420433
});
421434
});
422435
}
@@ -701,6 +714,76 @@ describe('datatype', () => {
701714
const generateBigInt = faker.datatype.bigInt();
702715
expect(generateBigInt).toBeTypeOf('bigint');
703716
});
717+
718+
it('should generate a big bigInt value with low delta', () => {
719+
const min = 999999999n;
720+
const max = 1000000000n;
721+
const generateBigInt = faker.datatype.bigInt({ min, max });
722+
expect(generateBigInt).toBeTypeOf('bigint');
723+
expect(generateBigInt).toBeGreaterThanOrEqual(min);
724+
expect(generateBigInt).toBeLessThanOrEqual(max);
725+
});
726+
727+
it('should return a random bigint given a maximum value as BigInt', () => {
728+
const max = 10n;
729+
expect(faker.datatype.bigInt(max)).toBeGreaterThanOrEqual(0n);
730+
expect(faker.datatype.bigInt(max)).toBeLessThanOrEqual(max);
731+
});
732+
733+
it('should return a random bigint given a maximum value as Object', () => {
734+
const options = { max: 10n };
735+
expect(faker.datatype.bigInt(options)).toBeGreaterThanOrEqual(0n);
736+
expect(faker.datatype.bigInt(options)).toBeLessThanOrEqual(
737+
options.max
738+
);
739+
});
740+
741+
it('should return a random bigint given a maximum value of 0', () => {
742+
const options = { max: 0n };
743+
expect(faker.datatype.bigInt(options)).toBe(0n);
744+
});
745+
746+
it('should return a random bigint given a negative bigint minimum and maximum value of 0', () => {
747+
const options = { min: -100n, max: 0n };
748+
expect(faker.datatype.bigInt(options)).toBeGreaterThanOrEqual(
749+
options.min
750+
);
751+
expect(faker.datatype.bigInt(options)).toBeLessThanOrEqual(
752+
options.max
753+
);
754+
});
755+
756+
it('should return a random bigint between a range', () => {
757+
const options = { min: 22, max: 33 };
758+
for (let i = 0; i < 100; i++) {
759+
const randomBigInt = faker.datatype.bigInt(options);
760+
expect(randomBigInt).toBeGreaterThanOrEqual(options.min);
761+
expect(randomBigInt).toBeLessThanOrEqual(options.max);
762+
}
763+
});
764+
765+
it('should succeed with success-rate', () => {
766+
const min = 0n;
767+
const max = 1000000000000n;
768+
const randomBigInt = faker.datatype.bigInt({ min, max });
769+
expect(randomBigInt).toBeGreaterThanOrEqual(min);
770+
expect(randomBigInt).toBeLessThanOrEqual(max);
771+
});
772+
773+
it('should not mutate the input object', () => {
774+
const initialMin = 1n;
775+
const initialOtherProperty = 'hello darkness my old friend';
776+
const input: {
777+
min?: bigint;
778+
max?: bigint;
779+
otherProperty: string;
780+
} = Object.freeze({
781+
min: initialMin,
782+
otherProperty: initialOtherProperty,
783+
});
784+
785+
expect(() => faker.datatype.bigInt(input)).not.toThrow();
786+
});
704787
});
705788
}
706789
});

0 commit comments

Comments
 (0)