aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinigami <[email protected]>2022-04-08 22:17:57 +0200
committerGitHub <[email protected]>2022-04-08 20:17:57 +0000
commit651d684807177f633ef3ffa25f63c615ee17341d (patch)
treed1adc6fdce72aefe8d5a5ea83ec159ac1a61af8f
parent0dfe9a3bd457b8ceaabd20e67a2a71a6a2cabc9a (diff)
downloadfaker-651d684807177f633ef3ffa25f63c615ee17341d.tar.xz
faker-651d684807177f633ef3ffa25f63c615ee17341d.zip
refactor: datatype number (#798)
-rw-r--r--src/datatype.ts25
-rw-r--r--test/datatype.spec.ts92
2 files changed, 74 insertions, 43 deletions
diff --git a/src/datatype.ts b/src/datatype.ts
index 7e4a3cc1..29a4950b 100644
--- a/src/datatype.ts
+++ b/src/datatype.ts
@@ -1,4 +1,5 @@
import type { Faker } from '.';
+import { FakerError } from './errors/faker-error';
import { deprecated } from './internal/deprecated';
/**
@@ -24,7 +25,7 @@ export class Datatype {
* @param options.max Upper bound for generated number. Defaults to `min + 99999`.
* @param options.precision Precision of the generated number. Defaults to `1`.
*
- * @throws When options define `max < min`
+ * @throws When options define `max < min`.
*
* @example
* faker.datatype.number() // 55422
@@ -35,25 +36,25 @@ export class Datatype {
* faker.datatype.number({ min: 10, max: 100, precision: 0.01 }) // 36.94
*/
number(
- options?: number | { min?: number; max?: number; precision?: number }
+ options: number | { min?: number; max?: number; precision?: number } = 99999
): number {
- const opts = typeof options === 'number' ? { max: options } : options ?? {};
+ if (typeof options === 'number') {
+ options = { max: options };
+ }
- const min = typeof opts.min === 'number' ? opts.min : 0;
- let max = typeof opts.max === 'number' ? opts.max : min + 99999;
- const precision = typeof opts.precision === 'number' ? opts.precision : 1;
+ const { min = 0, precision = 1 } = options;
+ const max = options.max ?? min + 99999;
- if (max < min) {
- throw new Error(`Max ${max} should be larger then min ${min}`);
+ if (max === min) {
+ return min;
}
- // Make the range inclusive of the max value
- if (max >= 0) {
- max += precision;
+ if (max < min) {
+ throw new FakerError(`Max ${max} should be larger then min ${min}.`);
}
const randomNumber = Math.floor(
- this.faker.mersenne.rand(max / precision, min / precision)
+ this.faker.mersenne.rand(max / precision + 1, min / precision)
);
// Workaround problem in float point arithmetics for e.g. 6681493 / 0.01
diff --git a/test/datatype.spec.ts b/test/datatype.spec.ts
index 8c7d572a..696c501c 100644
--- a/test/datatype.spec.ts
+++ b/test/datatype.spec.ts
@@ -170,7 +170,7 @@ const seededRuns = [
number: new Date('2000-06-14T02:54:42.082Z'),
withMin: new Date('2065-11-10T19:27:20.915Z'),
withMax: new Date('2001-03-20T11:14:25.251Z'),
- withMinMax: new Date('1789-03-26T15:44:45.218Z'),
+ withMinMax: new Date('1789-03-26T15:44:45.219Z'),
},
string: {
noArgs: 'wKti5-}$_/',
@@ -297,7 +297,7 @@ describe('datatype', () => {
expect(() => {
faker.datatype.number({ min, max });
- }).toThrowError(`Max ${max} should be larger then min ${min}`);
+ }).toThrowError(`Max ${max} should be larger then min ${min}.`);
});
});
@@ -431,38 +431,73 @@ describe('datatype', () => {
describe('number', () => {
it('should return a random number given a maximum value as Number', () => {
const max = 10;
- expect(faker.datatype.number(max)).greaterThanOrEqual(0);
- expect(faker.datatype.number(max)).lessThanOrEqual(max);
+
+ const actual = faker.datatype.number(max);
+
+ expect(actual).greaterThanOrEqual(0);
+ expect(actual).lessThanOrEqual(max);
});
it('should return a random number given a maximum value as Object', () => {
const options = { max: 10 };
- expect(faker.datatype.number(options)).greaterThanOrEqual(0);
- expect(faker.datatype.number(options)).lessThanOrEqual(options.max);
+
+ const actual = faker.datatype.number(options);
+
+ expect(actual).greaterThanOrEqual(0);
+ expect(actual).lessThanOrEqual(options.max);
});
it('should return a random number given a maximum value of 0', () => {
const options = { max: 0 };
- expect(faker.datatype.number(options)).toBe(0);
+
+ const actual = faker.datatype.number(options);
+
+ expect(actual).toBe(0);
});
it('should return a random number given a negative number minimum and maximum value of 0', () => {
const options = { min: -100, max: 0 };
- expect(faker.datatype.number(options)).greaterThanOrEqual(
- options.min
- );
- expect(faker.datatype.number(options)).lessThanOrEqual(options.max);
+
+ const actual = faker.datatype.number(options);
+
+ expect(actual).greaterThanOrEqual(options.min);
+ expect(actual).lessThanOrEqual(options.max);
});
it('should return a random number between a range', () => {
const options = { min: 22, max: 33 };
for (let i = 0; i < 100; i++) {
- const randomNumber = faker.datatype.number(options);
- expect(randomNumber).greaterThanOrEqual(options.min);
- expect(randomNumber).lessThanOrEqual(options.max);
+ const actual = faker.datatype.number(options);
+ expect(actual).greaterThanOrEqual(options.min);
+ expect(actual).lessThanOrEqual(options.max);
}
});
+ it('should return inclusive negative max value', () => {
+ let foundNegative4 = false;
+ let foundNegative5 = false;
+
+ for (let iter = 0; iter < 1000; iter++) {
+ const actual = faker.datatype.number({ min: -5, max: -4 });
+
+ if (actual === -4) {
+ foundNegative4 = true;
+ } else if (actual === -5) {
+ foundNegative5 = true;
+ }
+
+ expect(actual).greaterThanOrEqual(-5);
+ expect(actual).lessThanOrEqual(-4);
+
+ if (foundNegative4 && foundNegative5) {
+ break;
+ }
+ }
+
+ expect(foundNegative4).toBeTruthy();
+ expect(foundNegative5).toBeTruthy();
+ });
+
it('provides numbers with a given precision', () => {
const options = { min: 0, max: 1.5, precision: 0.5 };
const results = Array.from(
@@ -481,32 +516,27 @@ describe('datatype', () => {
it('provides numbers with a with exact precision', () => {
const options = { min: 0.5, max: 0.99, precision: 0.01 };
for (let i = 0; i < 100; i++) {
- const number = faker.datatype.number(options);
- expect(number).toBe(Number(number.toFixed(2)));
+ const actual = faker.datatype.number(options);
+ expect(actual).toBe(Number(actual.toFixed(2)));
}
});
it('should not mutate the input object', () => {
- const initalMin = 1;
- const initalPrecision = 1;
- const initalOtherProperty = 'hello darkness my old friend';
+ const initialMin = 1;
+ const initialPrecision = 1;
+ const initialOtherProperty = 'hello darkness my old friend';
const input: {
min?: number;
max?: number;
precision?: number;
otherProperty: string;
- } = {
- min: initalMin,
- precision: initalPrecision,
- otherProperty: initalOtherProperty,
- };
-
- faker.datatype.number(input);
-
- expect(input.min).toBe(initalMin);
- expect(input.precision).toBe(initalPrecision);
- expect(input.max).toBe(undefined);
- expect(input.otherProperty).toBe(initalOtherProperty);
+ } = Object.freeze({
+ min: initialMin,
+ precision: initialPrecision,
+ otherProperty: initialOtherProperty,
+ });
+
+ expect(() => faker.datatype.number(input)).not.toThrow();
});
});