Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(number): deprecate precision in favor of multipleOf in float #2564

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 31 additions & 9 deletions src/modules/number/index.ts
@@ -1,4 +1,5 @@
import { FakerError } from '../../errors/faker-error';
import { deprecated } from '../../internal/deprecated';
import { SimpleModuleBase } from '../../internal/module-base';

/**
Expand Down Expand Up @@ -84,22 +85,26 @@ export class NumberModule extends SimpleModuleBase {
}

/**
* Returns a single random floating-point number for a given precision or range and precision.
* The lower bound is inclusive, the upper bound is exclusive, unless precision is passed.
* Returns a single random floating-point number for a given multipleOf or range and multipleOf.
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
* The lower bound is inclusive, the upper bound is exclusive, unless multipleOf is passed.
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
*
* @param options Upper bound or options object.
* @param options.min Lower bound for generated number. Defaults to `0.0`.
* @param options.max Upper bound for generated number. Defaults to `1.0`.
* @param options.precision Precision of the generated number, for example `0.01` will round to 2 decimal points.
* If precision is passed, the upper bound is inclusive.
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
* @param options.multipleOf The generated number will be a multiple of this property.
* This property can be used to achieve specific decimal points.
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
* For example `0.01` will round to 2 decimal points.
* If multipleOf is passed, the upper bound is inclusive.
*
* @example
* faker.number.float() // 0.5688541042618454
* faker.number.float(3) // 2.367973240558058
* faker.number.float({ min: -1000000 }) //-780678.849672846
* faker.number.float({ max: 100 }) // 17.3687307164073
* faker.number.float({ precision: 0.1 }) // 0.9
* faker.number.float({ min: 10, max: 100, precision: 0.001 }) // 35.415
* faker.number.float({ multipleOf: 0.25 }) // 3.75
* faker.number.float({ min: 10, max: 100, multipleOf: 0.001 }) // 35.415
*
* @since 8.0.0
*/
Expand All @@ -121,8 +126,15 @@ export class NumberModule extends SimpleModuleBase {
max?: number;
/**
* Precision of the generated number.
*
* @deprecated Use `multipleOf` instead.
*/
precision?: number;
/**
* The generated number will be a multiple of this property.
* If multipleOf is passed, the upper bound is inclusive.
*/
multipleOf?: number;
} = {}
): number {
if (typeof options === 'number') {
Expand All @@ -131,7 +143,17 @@ export class NumberModule extends SimpleModuleBase {
};
}

const { min = 0, max = 1, precision } = options;
// eslint-disable-next-line deprecation/deprecation
const { min = 0, max = 1, precision, multipleOf = precision } = options;

if (precision !== undefined) {
deprecated({
deprecated: 'faker.number.float({ precision })',
proposed: 'faker.number.float({ multipleOf })',
since: '8.4',
until: '9.0',
});
}

if (max === min) {
return min;
Expand All @@ -141,12 +163,12 @@ export class NumberModule extends SimpleModuleBase {
throw new FakerError(`Max ${max} should be greater than min ${min}.`);
}

if (precision !== undefined) {
if (precision <= 0) {
throw new FakerError(`Precision should be greater than 0.`);
if (multipleOf !== undefined) {
if (multipleOf <= 0) {
throw new FakerError(`Multiple of should be greater than 0.`);
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
}

const factor = 1 / precision;
const factor = 1 / multipleOf;
const int = this.int({
min: min * factor,
max: max * factor,
Expand Down
6 changes: 6 additions & 0 deletions test/modules/__snapshots__/number.spec.ts.snap
Expand Up @@ -26,6 +26,8 @@ exports[`number > 42 > float > with min 1`] = `-25.894775084685534`;

exports[`number > 42 > float > with min and max 1`] = `-0.4260473116301`;

exports[`number > 42 > float > with min, max and multipleOf 1`] = `-0.4261`;

exports[`number > 42 > float > with min, max and precision 1`] = `-0.4261`;

exports[`number > 42 > float > with plain number 1`] = `1.498160457238555`;
Expand Down Expand Up @@ -74,6 +76,8 @@ exports[`number > 1211 > float > with min 1`] = `-2.073633389081806`;

exports[`number > 1211 > float > with min and max 1`] = `61.06573706539348`;

exports[`number > 1211 > float > with min, max and multipleOf 1`] = `61.0658`;

exports[`number > 1211 > float > with min, max and precision 1`] = `61.0658`;

exports[`number > 1211 > float > with plain number 1`] = `3.7140806149691343`;
Expand Down Expand Up @@ -122,6 +126,8 @@ exports[`number > 1337 > float > with min 1`] = `-30.732938923640177`;

exports[`number > 1337 > float > with min and max 1`] = `-12.915260942419991`;

exports[`number > 1337 > float > with min, max and multipleOf 1`] = `-12.9153`;

exports[`number > 1337 > float > with min, max and precision 1`] = `-12.9153`;

exports[`number > 1337 > float > with plain number 1`] = `1.048098704777658`;
Expand Down
64 changes: 62 additions & 2 deletions test/modules/number.spec.ts
Expand Up @@ -25,6 +25,11 @@ describe('number', () => {
min: -42,
max: 69,
precision: 0.0001,
})
.it('with min, max and multipleOf', {
min: -42,
max: 69,
multipleOf: 0.0001,
});
});

Expand Down Expand Up @@ -242,6 +247,22 @@ describe('number', () => {
expect(results).toEqual([0, 0.5, 1, 1.5]);
});

it('provides numbers with a given multipleOf of 0.5 steps', () => {
const results = [
...new Set(
Array.from({ length: 50 }, () =>
faker.number.float({
min: 0,
max: 1.5,
multipleOf: 0.5,
})
)
),
].sort();

expect(results).toEqual([0, 0.5, 1, 1.5]);
});

it('provides numbers with a given precision of 0.4 steps', () => {
const results = [
...new Set(
Expand All @@ -258,6 +279,22 @@ describe('number', () => {
expect(results).toEqual([0, 0.4, 0.8, 1.2, 1.6]);
});

it('provides numbers with a given multipleOf of 0.4 steps', () => {
const results = [
...new Set(
Array.from({ length: 50 }, () =>
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
faker.number.float({
min: 0,
max: 1.9,
multipleOf: 0.4,
})
)
),
].sort();

expect(results).toEqual([0, 0.4, 0.8, 1.2, 1.6]);
});

it('provides numbers with an exact precision', () => {
for (let i = 0; i < 100; i++) {
const actual = faker.number.float({
Expand All @@ -269,15 +306,38 @@ describe('number', () => {
}
});

it('provides numbers with an exact precision via multipleOf', () => {
for (let i = 0; i < 100; i++) {
const actual = faker.number.float({
min: 0.5,
max: 0.99,
multipleOf: 0.01,
});
expect(actual).toBe(Number(actual.toFixed(2)));
}
});

it('throws an error for precision 0', () => {
expect(() => faker.number.float({ precision: 0 })).toThrow(
new FakerError('Precision should be greater than 0.')
new FakerError('Multiple of should be greater than 0.')
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
);
});

it('throws an error for multipleOf 0', () => {
expect(() => faker.number.float({ multipleOf: 0 })).toThrow(
new FakerError('Multiple of should be greater than 0.')
);
});

it('throws an error for negative precision', () => {
expect(() => faker.number.float({ precision: -0.01 })).toThrow(
new FakerError('Precision should be greater than 0.')
new FakerError('Multiple of should be greater than 0.')
);
});

it('throws an error for negative multipleOf', () => {
expect(() => faker.number.float({ multipleOf: -0.01 })).toThrow(
new FakerError('Multiple of should be greater than 0.')
);
});

Expand Down