From 6c9bcedd828d43ac78f202ac5eea8ad693f99752 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Thu, 13 Apr 2023 22:56:47 +0200 Subject: [PATCH] feat(datatype): reimplement datatype module --- docs/guide/upgrading.md | 37 +++ src/modules/datatype/index.ts | 379 ++++++++++++++--------- src/modules/number/index.ts | 5 + src/modules/string/index.ts | 2 + test/__snapshots__/datatype.spec.ts.snap | 210 ++++++++++--- test/__snapshots__/helpers.spec.ts.snap | 82 ++--- test/all_functional.spec.ts | 2 + test/datatype.spec.ts | 291 +++++------------ test/helpers.spec.ts | 6 +- 9 files changed, 567 insertions(+), 447 deletions(-) diff --git a/docs/guide/upgrading.md b/docs/guide/upgrading.md index 0572f5f1149..b85df447870 100644 --- a/docs/guide/upgrading.md +++ b/docs/guide/upgrading.md @@ -139,6 +139,24 @@ faker.name.prefix(); // 'Mr' fakerZH_CN.person.prefix(); // throws a FakerError ``` +### Behavior of `faker.datatype` module has changed, as has the scope for which it is to be used + +The `faker.datatype` module is now only intended to be used for generating values that are comparable against JavaScript's `typeof` operator. +This means that e.g. `faker.datatype.number` will return any number (so also e.g. `NaN`), `faker.datatype.string` can now also return an empty string `''`, etc. + +```js +typeof faker.datatype.bigint() === 'bigint'; // true +typeof faker.datatype.boolean() === 'boolean'; // true +typeof faker.datatype.function() === 'function'; // true +typeof faker.datatype.number() === 'number'; // true +typeof faker.datatype.object() === 'object'; // true +typeof faker.datatype.string() === 'string'; // true +typeof faker.datatype.symbol() === 'symbol'; // true +typeof faker.datatype.undefined() === 'undefined'; // true +``` + +Every other method in `faker.datatype` has been moved to a more appropriate module or is marked for removal in v9.0. + ### `faker.mersenne` and `faker.helpers.repeatString` removed `faker.mersenne` and `faker.helpers.repeatString` were only ever intended for internal use, and are no longer available. @@ -311,6 +329,25 @@ faker.number.float({ max: 100, precision: 0.01 }); // 35.21 | `faker.datatype.float` | `faker.number.float` | | `faker.datatype.bigInt` | `faker.number.bigInt` | +### String method of `faker.datatype` moved to new `faker.string` module + +The string method previously found in `faker.datatype` have been moved to a new `faker.string` module. +For the old `faker.datatype.string` method you should replace with `faker.string.sample` or one of the other methods that suites your needs. + +```js +// OLD +faker.datatype.string(); // 'Zo!.:*e>wR' +faker.datatype.string(5); // '6Bye8' + +// NEW +faker.string.sample(); // 'Zo!.:*e>wR' +faker.string.sample(5); // '6Bye8' +``` + +| Old method | New method | +| ----------------------- | --------------------- | +| `faker.datatype.string` | `faker.string.sample` | + ### Deprecation of `faker.datatype.array` The method `faker.datatype.array` has been deprecated and will be removed in v9. diff --git a/src/modules/datatype/index.ts b/src/modules/datatype/index.ts index e776784c8fd..a5174d2d11c 100644 --- a/src/modules/datatype/index.ts +++ b/src/modules/datatype/index.ts @@ -2,13 +2,28 @@ import type { Faker } from '../..'; import { deprecated } from '../../internal/deprecated'; /** - * Module to generate various primitive values and data types. + * Module to generate values that can be checked against JavaScript's `typeof` operator. * * ### Overview * - * Most of the methods in this module are deprecated and have been moved to other modules like [`faker.number`](https://next.fakerjs.dev/api/number.html) and [`faker.string`](https://next.fakerjs.dev/api/string.html), see individual entries for replacements. + * This module provides methods to generate values that can be checked against JavaScript's `typeof` operator. * - * For a simple random true or false value, use [`boolean()`](https://next.fakerjs.dev/api/datatype.html#boolean). + * ```ts + * typeof faker.datatype.bigint() === 'bigint' // true + * typeof faker.datatype.boolean() === 'boolean' // true + * typeof faker.datatype.function() === 'function' // true + * typeof faker.datatype.number() === 'number' // true + * typeof faker.datatype.object() === 'object' // true + * typeof faker.datatype.string() === 'string' // true + * typeof faker.datatype.symbol() === 'symbol' // true + * typeof faker.datatype.undefined() === 'undefined' // true + * ``` + * + * Note that `boolean()` method can be enriched with a probability of returning `true`. + * + * The other methods are only intended to return a value of the specified type, but nothing more. + * + * If you want more specific values, use e.g. [`faker.number`](https://next.fakerjs.dev/api/number.html) or [`faker.string`](https://next.fakerjs.dev/api/string.html) module instead. */ export class DatatypeModule { constructor(private readonly faker: Faker) { @@ -25,71 +40,245 @@ export class DatatypeModule { } /** - * Returns a single random number between zero and the given max value or the given range with the specified precision. - * The bounds are inclusive. + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'bigint'` operator. * - * @param options Maximum value or options object. - * @param options.min Lower bound for generated number. Defaults to `0`. - * @param options.max Upper bound for generated number. Defaults to `min + 99999`. - * @param options.precision Precision of the generated number. Defaults to `1`. + * @see faker.number.bigInt() If you want to generate more specific values. * - * @throws When options define `max < min`. + * @example + * faker.datatype.bigint() // 55422n * - * @see faker.number.int() for the default precision of `1` - * @see faker.number.float() for a custom precision + * @since 8.0.0 + */ + bigint(): bigint { + return this.faker.number.bigInt(); + } + + /** + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'boolean'` operator. + * + * **Note:** + * A probability of `0.75` results in `true` being returned `75%` of the calls; likewise `0.3` => `30%`. + * If the probability is `<= 0.0`, it will always return `false`. + * If the probability is `>= 1.0`, it will always return `true`. + * + * @param options The optional options object or the probability (`[0.00, 1.00]`) of returning `true`. Defaults to `0.5`. + * @param options.probability The probability (`[0.00, 1.00]`) of returning `true`. Defaults to `0.5`. * * @example - * faker.datatype.number() // 55422 - * faker.datatype.number(100) // 52 - * faker.datatype.number({ min: 1000000 }) // 1031433 - * faker.datatype.number({ max: 100 }) // 42 - * faker.datatype.number({ precision: 0.01 }) // 64246.18 - * faker.datatype.number({ min: 10, max: 100, precision: 0.01 }) // 36.94 + * faker.datatype.boolean() // false + * faker.datatype.boolean(0.9) // true + * faker.datatype.boolean({ probability: 0.1 }) // false * * @since 5.5.0 - * - * @deprecated Use `faker.number.int()` or `faker.number.float()` instead. */ - number( + boolean( options: | number | { /** - * Lower bound for generated number. - * - * @default 0 - */ - min?: number; - /** - * Upper bound for generated number. - * - * @default min + 99999 - */ - max?: number; - /** - * Precision of the generated number. + * The probability (`[0.00, 1.00]`) of returning `true`. * - * @default 1 + * @default 0.5 */ - precision?: number; - } = 99999 - ): number { - deprecated({ - deprecated: 'faker.datatype.number()', - proposed: 'faker.number.int()', - since: '8.0', - until: '9.0', - }); - + probability?: number; + } = {} + ): boolean { if (typeof options === 'number') { - options = { max: options }; + options = { + probability: options, + }; } - const { min = 0, max = min + 99999, precision = 1 } = options; + const { probability = 0.5 } = options; + if (probability <= 0) { + return false; + } - return this.faker.number.float({ min, max, precision }); + if (probability >= 1) { + // This check is required to avoid returning false when float() returns 1 + return true; + } + + return this.faker.number.float() < probability; + } + + /** + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'function'` operator. + * + * **Note:** + * The returned function can be empty, throw an error, return a promise or return a value of any type. + * + * @example + * faker.datatype.function() // () => ({}) + * faker.datatype.function() // () => 55422n + * faker.datatype.function() // () => false + * faker.datatype.function() // () => Promise.resolve() + * + * @since 8.0.0 + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function(): () => any { + return this.faker.helpers.weightedArrayElement<() => unknown>([ + { + weight: 1, + value: () => { + // empty function + }, + }, + { + weight: 8, + value: () => + // TODO @Shinigami92 2023-04-14: This can later be refactored with `faker.helpers.objectValues(this)()` when the deprecated methods are removed + this[ + this.faker.helpers.arrayElement([ + 'bigint', + 'boolean', + 'function', + 'number', + 'object', + 'string', + 'symbol', + 'undefined', + ] as const) + ](), + }, + { + weight: 1, + value: () => { + throw new Error(); + }, + }, + { + weight: 1, + value: () => Promise.resolve(), + }, + { + weight: 1, + value: () => Promise.reject(), + }, + { + weight: 1, + value: () => + new Promise(() => { + // empty promise that does not resolve or reject + }), + }, + ]); + } + + /** + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'number'` operator. + * + * @param options This parameter does nothing and is deprecated. Use `faker.number.float(options)` instead. + * + * @see faker.number.int() If you want to generate more specific values. + * @see faker.number.float() If you want to generate more specific values. + * + * @example + * faker.datatype.number() // 55422 + * faker.datatype.number() // 0.5688541042618454 + * faker.datatype.number() // NaN + * faker.datatype.number() // Infinity + * faker.datatype.number() // Number.POSITIVE_INFINITY + * faker.datatype.number() // Number.NEGATIVE_INFINITY + * + * @since 5.5.0 + */ + number(options?: unknown): number { + if (options != null) { + deprecated({ + deprecated: 'faker.datatype.number(options)', + proposed: 'faker.number.float(options)', + since: '8.0', + until: '9.0', + }); + } + + return this.faker.helpers.weightedArrayElement([ + { weight: 1, value: () => this.faker.number.float() }, + { weight: 1, value: () => this.faker.number.int() }, + { weight: 1, value: () => NaN }, + { weight: 1, value: () => Infinity }, + { weight: 1, value: () => Number.POSITIVE_INFINITY }, + { weight: 1, value: () => Number.NEGATIVE_INFINITY }, + ])(); + } + + /** + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'object'` operator. + * + * @example + * faker.datatype.object() // {} + * faker.datatype.object() // [] + * faker.datatype.object() // new Date() + * faker.datatype.object() // null + * + * @since 8.0.0 + */ + object(): unknown { + return this.faker.helpers.weightedArrayElement<() => unknown>([ + { weight: 1, value: () => ({}) }, + { weight: 1, value: () => [] }, + { weight: 1, value: () => this.datetime() }, + { weight: 1, value: () => null }, + ])(); + } + + /** + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'string'` operator. + * + * @param length This parameter does nothing and is deprecated. Use `faker.string.sample(length)` instead. + * + * @see faker.string.sample() If you want to generate more specific values. + * + * @example + * faker.datatype.string() // 'Zo!.:*e>wR' + * + * @since 5.5.0 + */ + string(length?: unknown): string { + if (length != null) { + deprecated({ + deprecated: 'faker.datatype.string(length)', + proposed: 'faker.string.sample(length)', + since: '8.0', + until: '9.0', + }); + } + + return this.faker.helpers.weightedArrayElement([ + { weight: 1, value: () => this.faker.string.sample() }, + { weight: 1, value: () => '' }, + ])(); } + /** + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'symbol'` operator. + * + * @example + * faker.datatype.symbol() // Symbol('fEcAaCVbaR') + * + * @since 8.0.0 + */ + symbol(): symbol { + return Symbol(this.faker.string.alpha({ length: { min: 3, max: 20 } })); + } + + /** + * Returns a value that will result in `true` when checked against JavaScript's `typeof value === 'undefined'` operator. + * + * @example + * faker.datatype.undefined() // undefined + * faker.datatype.undefined() // void 0 + * + * @since 8.0.0 + */ + undefined(): undefined { + return this.faker.helpers.arrayElement([undefined, void 0]); + } + + // Deprecated methods + /** * Returns a single random floating-point number for the given precision or range and precision. * @@ -222,50 +411,6 @@ export class DatatypeModule { return this.faker.date.between({ from: min, to: max }); } - /** - * Returns a string containing UTF-16 chars between 33 and 125 (`!` to `}`). - * - * @param options Length of the generated string or an options object. Defaults to `{}`. - * @param options.length Length of the generated string. Max length is `2^20`. Defaults to `10`. - * - * @see faker.string.sample() - * - * @example - * faker.datatype.string() // 'Zo!.:*e>wR' - * faker.datatype.string(5) // '6Bye8' - * faker.datatype.string({ length: 7 }) // 'dzOT00e' - * - * @since 5.5.0 - * - * @deprecated Use `faker.string.sample()` instead. - */ - string( - options: - | number - | { - /** - * Length of the generated string. Max length is `2^20`. - * - * @default 10 - */ - length?: number; - } = {} - ): string { - deprecated({ - deprecated: 'faker.datatype.string()', - proposed: 'faker.string.sample()', - since: '8.0', - until: '9.0', - }); - if (typeof options === 'number') { - options = { length: options }; - } - - const { length = 10 } = options; - - return this.faker.string.sample(length); - } - /** * Returns a UUID v4 ([Universally Unique Identifier](https://en.wikipedia.org/wiki/Universally_unique_identifier)). * @@ -288,56 +433,6 @@ export class DatatypeModule { return this.faker.string.uuid(); } - /** - * Returns the boolean value true or false. - * - * **Note:** - * A probability of `0.75` results in `true` being returned `75%` of the calls; likewise `0.3` => `30%`. - * If the probability is `<= 0.0`, it will always return `false`. - * If the probability is `>= 1.0`, it will always return `true`. - * The probability is limited to two decimal places. - * - * @param options The optional options object or the probability (`[0.00, 1.00]`) of returning `true`. Defaults to `0.5`. - * @param options.probability The probability (`[0.00, 1.00]`) of returning `true`. Defaults to `0.5`. - * - * @example - * faker.datatype.boolean() // false - * faker.datatype.boolean(0.9) // true - * faker.datatype.boolean({ probability: 0.1 }) // false - * - * @since 5.5.0 - */ - boolean( - options: - | number - | { - /** - * The probability (`[0.00, 1.00]`) of returning `true`. - * - * @default 0.5 - */ - probability?: number; - } = {} - ): boolean { - if (typeof options === 'number') { - options = { - probability: options, - }; - } - - const { probability = 0.5 } = options; - if (probability <= 0) { - return false; - } - - if (probability >= 1) { - // This check is required to avoid returning false when float() returns 1 - return true; - } - - return this.faker.number.float() < probability; - } - /** * Returns a [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) number. * diff --git a/src/modules/number/index.ts b/src/modules/number/index.ts index 92751fe627c..28225c3475a 100644 --- a/src/modules/number/index.ts +++ b/src/modules/number/index.ts @@ -41,6 +41,7 @@ export class NumberModule { * @throws When options define `max < min`. * * @see faker.string.numeric() If you would like to generate a `string` of digits with a given length (range). + * @see faker.datatype.number() If you would like to generate a `number` that just fulfills the `typeof value === 'number'` check but can e.g. return `NaN`. * * @example * faker.number.int() // 55422 @@ -106,6 +107,8 @@ export class NumberModule { * @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. * + * @see faker.datatype.number() If you would like to generate a `number` that just fulfills the `typeof value === 'number'` check but can e.g. return `NaN`. + * * @example * faker.number.float() // 0.5688541042618454 * faker.number.float(3) // 2.367973240558058 @@ -324,6 +327,8 @@ export class NumberModule { * * @throws When options define `max < min`. * + * @see faker.datatype.bigint() If you would like to generate a `bigint` that just fulfills the `typeof value === 'bigint'` check. + * * @example * faker.number.bigInt() // 55422n * faker.number.bigInt(100n) // 52n diff --git a/src/modules/string/index.ts b/src/modules/string/index.ts index 4c5a7dc32f8..f2edf748638 100644 --- a/src/modules/string/index.ts +++ b/src/modules/string/index.ts @@ -642,6 +642,8 @@ export class StringModule { * @param length.min The minimum number of characters to generate. * @param length.max The maximum number of characters to generate. * + * @see faker.datatype.string() If you would like to generate a `string` that just fulfills the `typeof value === 'string'` check. + * * @example * faker.string.sample() // 'Zo!.:*e>wR' * faker.string.sample(5) // '6Bye8' diff --git a/test/__snapshots__/datatype.spec.ts.snap b/test/__snapshots__/datatype.spec.ts.snap index 41c14158415..015dfb9b370 100644 --- a/test/__snapshots__/datatype.spec.ts.snap +++ b/test/__snapshots__/datatype.spec.ts.snap @@ -37,6 +37,16 @@ exports[`datatype > 42 > bigInt > noArgs 1`] = `379177551410048n`; exports[`datatype > 42 > bigInt > with value 1`] = `37n`; +exports[`datatype > 42 > bigint > noArgs 1`] = `379177551410048n`; + +exports[`datatype > 42 > bigint > noArgs 2`] = `361760097892019n`; + +exports[`datatype > 42 > bigint > noArgs 3`] = `163650402563102n`; + +exports[`datatype > 42 > bigint > noArgs 4`] = `932407613595408n`; + +exports[`datatype > 42 > bigint > noArgs 5`] = `661400999583300n`; + exports[`datatype > 42 > boolean > noArgs 1`] = `true`; exports[`datatype > 42 > boolean > noArgs 2`] = `false`; @@ -83,6 +93,16 @@ exports[`datatype > 42 > float > with min and max 1`] = `-0.43`; exports[`datatype > 42 > float > with min, max and precision 1`] = `-0.4261`; +exports[`datatype > 42 > function > noArgs 1`] = `[Function]`; + +exports[`datatype > 42 > function > noArgs 2`] = `[Function]`; + +exports[`datatype > 42 > function > noArgs 3`] = `[Function]`; + +exports[`datatype > 42 > function > noArgs 4`] = `[Function]`; + +exports[`datatype > 42 > function > noArgs 5`] = `[Function]`; + exports[`datatype > 42 > hexadecimal > noArgs 1`] = `"0x8"`; exports[`datatype > 42 > hexadecimal > with casing 1`] = `"0x8"`; @@ -95,31 +115,55 @@ exports[`datatype > 42 > hexadecimal > with prefix 1`] = `"0x8"`; exports[`datatype > 42 > json 1`] = `"{\\"foo\\":\\"ky2eiXX/J/\\",\\"bar\\":\\"&Kq@X.b]\\\\\\"&\\",\\"bike\\":6503186795855872,\\"a\\":8453731307749376,\\"b\\":\\"!1}2Z=YQ!I\\",\\"name\\":\\" 42 > number > noArgs 1`] = `37454`; +exports[`datatype > 42 > number > noArgs 1`] = `NaN`; + +exports[`datatype > 42 > number > noArgs 2`] = `Infinity`; + +exports[`datatype > 42 > number > noArgs 3`] = `-Infinity`; + +exports[`datatype > 42 > number > noArgs 4`] = `6593215255805952`; + +exports[`datatype > 42 > number > noArgs 5`] = `Infinity`; + +exports[`datatype > 42 > object > noArgs 1`] = `[]`; + +exports[`datatype > 42 > object > noArgs 2`] = `null`; + +exports[`datatype > 42 > object > noArgs 3`] = `null`; -exports[`datatype > 42 > number > repeated 1`] = `2`; +exports[`datatype > 42 > object > noArgs 4`] = `{}`; -exports[`datatype > 42 > number > repeated 2`] = `5`; +exports[`datatype > 42 > object > noArgs 5`] = `2075-10-07T15:29:05.646Z`; -exports[`datatype > 42 > number > repeated 3`] = `6`; +exports[`datatype > 42 > string > noArgs 1`] = `"ky2eiXX/J/"`; -exports[`datatype > 42 > number > repeated 4`] = `1`; +exports[`datatype > 42 > string > noArgs 2`] = `"&Kq@X.b]\\"&"`; -exports[`datatype > 42 > number > repeated 5`] = `5`; +exports[`datatype > 42 > string > noArgs 3`] = `""`; -exports[`datatype > 42 > number > with max 1`] = `26`; +exports[`datatype > 42 > string > noArgs 4`] = `""`; -exports[`datatype > 42 > number > with min 1`] = `37412`; +exports[`datatype > 42 > string > noArgs 5`] = `""`; -exports[`datatype > 42 > number > with min and max 1`] = `-1`; +exports[`datatype > 42 > symbol > noArgs 1`] = `Symbol(PXjMOFFix)`; -exports[`datatype > 42 > number > with min, max and precision 1`] = `-0.43`; +exports[`datatype > 42 > symbol > noArgs 2`] = `Symbol(fdxTr)`; -exports[`datatype > 42 > string > noArgs 1`] = `"Cky2eiXX/J"`; +exports[`datatype > 42 > symbol > noArgs 3`] = `Symbol(hKHbcYLRWlajZ)`; -exports[`datatype > 42 > string > with length option 1`] = `"Cky2eiXX/J/*&Kq@X.b]\\"&"`; +exports[`datatype > 42 > symbol > noArgs 4`] = `Symbol(GpFBaw)`; -exports[`datatype > 42 > string > with number 1`] = `"Cky2eiXX/J/*&Kq@X.b]\\"&{dnx4!1}2Z=YQ!I# 42 > symbol > noArgs 5`] = `Symbol(pBF)`; + +exports[`datatype > 42 > undefined > noArgs 1`] = `undefined`; + +exports[`datatype > 42 > undefined > noArgs 2`] = `undefined`; + +exports[`datatype > 42 > undefined > noArgs 3`] = `undefined`; + +exports[`datatype > 42 > undefined > noArgs 4`] = `undefined`; + +exports[`datatype > 42 > undefined > noArgs 5`] = `undefined`; exports[`datatype > 42 > uuid 1`] = `"5cf2bc99-2721-407d-8592-ba00fbdf302f"`; @@ -169,6 +213,16 @@ exports[`datatype > 1211 > bigInt > noArgs 1`] = `948721906162743n`; exports[`datatype > 1211 > bigInt > with value 1`] = `8n`; +exports[`datatype > 1211 > bigint > noArgs 1`] = `948721906162743n`; + +exports[`datatype > 1211 > bigint > noArgs 2`] = `167807667894289n`; + +exports[`datatype > 1211 > bigint > noArgs 3`] = `892459113694703n`; + +exports[`datatype > 1211 > bigint > noArgs 4`] = `390549125217359n`; + +exports[`datatype > 1211 > bigint > noArgs 5`] = `398335243510526n`; + exports[`datatype > 1211 > boolean > noArgs 1`] = `false`; exports[`datatype > 1211 > boolean > noArgs 2`] = `true`; @@ -215,6 +269,16 @@ exports[`datatype > 1211 > float > with min and max 1`] = `61.07`; exports[`datatype > 1211 > float > with min, max and precision 1`] = `61.0658`; +exports[`datatype > 1211 > function > noArgs 1`] = `[Function]`; + +exports[`datatype > 1211 > function > noArgs 2`] = `[Function]`; + +exports[`datatype > 1211 > function > noArgs 3`] = `[Function]`; + +exports[`datatype > 1211 > function > noArgs 4`] = `[Function]`; + +exports[`datatype > 1211 > function > noArgs 5`] = `[Function]`; + exports[`datatype > 1211 > hexadecimal > noArgs 1`] = `"0xE"`; exports[`datatype > 1211 > hexadecimal > with casing 1`] = `"0xe"`; @@ -227,31 +291,55 @@ exports[`datatype > 1211 > hexadecimal > with prefix 1`] = `"0xE"`; exports[`datatype > 1211 > json 1`] = `"{\\"foo\\":4134441414819840,\\"bar\\":7010029022478336,\\"bike\\":\\"-}$_/\`4hHA\\",\\"a\\":\\"afl\\\\\\"h^]dnw\\",\\"b\\":\\" 1211 > number > noArgs 1`] = `92852`; +exports[`datatype > 1211 > number > noArgs 1`] = `-Infinity`; + +exports[`datatype > 1211 > number > noArgs 2`] = `NaN`; -exports[`datatype > 1211 > number > repeated 1`] = `6`; +exports[`datatype > 1211 > number > noArgs 3`] = `-Infinity`; -exports[`datatype > 1211 > number > repeated 2`] = `3`; +exports[`datatype > 1211 > number > noArgs 4`] = `Infinity`; -exports[`datatype > 1211 > number > repeated 3`] = `6`; +exports[`datatype > 1211 > number > noArgs 5`] = `1169939440336896`; -exports[`datatype > 1211 > number > repeated 4`] = `5`; +exports[`datatype > 1211 > object > noArgs 1`] = `null`; -exports[`datatype > 1211 > number > repeated 5`] = `1`; +exports[`datatype > 1211 > object > noArgs 2`] = `[]`; -exports[`datatype > 1211 > number > with max 1`] = `64`; +exports[`datatype > 1211 > object > noArgs 3`] = `null`; -exports[`datatype > 1211 > number > with min 1`] = `92810`; +exports[`datatype > 1211 > object > noArgs 4`] = `null`; -exports[`datatype > 1211 > number > with min and max 1`] = `61`; +exports[`datatype > 1211 > object > noArgs 5`] = `{}`; -exports[`datatype > 1211 > number > with min, max and precision 1`] = `61.07`; +exports[`datatype > 1211 > string > noArgs 1`] = `""`; -exports[`datatype > 1211 > string > noArgs 1`] = `"wKti5-}$_/"`; +exports[`datatype > 1211 > string > noArgs 2`] = `"ti5-}$_/\`4"`; -exports[`datatype > 1211 > string > with length option 1`] = `"wKti5-}$_/\`4hHA0afl\\"h^"`; +exports[`datatype > 1211 > string > noArgs 3`] = `""`; -exports[`datatype > 1211 > string > with number 1`] = `"wKti5-}$_/\`4hHA0afl\\"h^]dnwI 1211 > string > noArgs 4`] = `"A0afl\\"h^]d"`; + +exports[`datatype > 1211 > string > noArgs 5`] = `""`; + +exports[`datatype > 1211 > symbol > noArgs 1`] = `Symbol(xUOlgZbIiJkNvsiKMQa)`; + +exports[`datatype > 1211 > symbol > noArgs 2`] = `Symbol(IILRWwpTZSZlxEVk)`; + +exports[`datatype > 1211 > symbol > noArgs 3`] = `Symbol(tGZxN)`; + +exports[`datatype > 1211 > symbol > noArgs 4`] = `Symbol(upW)`; + +exports[`datatype > 1211 > symbol > noArgs 5`] = `Symbol(BvY)`; + +exports[`datatype > 1211 > undefined > noArgs 1`] = `undefined`; + +exports[`datatype > 1211 > undefined > noArgs 2`] = `undefined`; + +exports[`datatype > 1211 > undefined > noArgs 3`] = `undefined`; + +exports[`datatype > 1211 > undefined > noArgs 4`] = `undefined`; + +exports[`datatype > 1211 > undefined > noArgs 5`] = `undefined`; exports[`datatype > 1211 > uuid 1`] = `"e7ec32f0-a2a3-4c65-b2bb-d0caabde64df"`; @@ -299,6 +387,16 @@ exports[`datatype > 1337 > bigInt > noArgs 1`] = `251225403255239n`; exports[`datatype > 1337 > bigInt > with value 1`] = `25n`; +exports[`datatype > 1337 > bigint > noArgs 1`] = `251225403255239n`; + +exports[`datatype > 1337 > bigint > noArgs 2`] = `273183063179148n`; + +exports[`datatype > 1337 > bigint > noArgs 3`] = `777034435573142n`; + +exports[`datatype > 1337 > bigint > noArgs 4`] = `864441148185986n`; + +exports[`datatype > 1337 > bigint > noArgs 5`] = `199848565608769n`; + exports[`datatype > 1337 > boolean > noArgs 1`] = `true`; exports[`datatype > 1337 > boolean > noArgs 2`] = `false`; @@ -345,6 +443,16 @@ exports[`datatype > 1337 > float > with min and max 1`] = `-12.92`; exports[`datatype > 1337 > float > with min, max and precision 1`] = `-12.9153`; +exports[`datatype > 1337 > function > noArgs 1`] = `[Function]`; + +exports[`datatype > 1337 > function > noArgs 2`] = `[Function]`; + +exports[`datatype > 1337 > function > noArgs 3`] = `[Function]`; + +exports[`datatype > 1337 > function > noArgs 4`] = `[Function]`; + +exports[`datatype > 1337 > function > noArgs 5`] = `[Function]`; + exports[`datatype > 1337 > hexadecimal > noArgs 1`] = `"0x5"`; exports[`datatype > 1337 > hexadecimal > with casing 1`] = `"0x5"`; @@ -357,31 +465,55 @@ exports[`datatype > 1337 > hexadecimal > with prefix 1`] = `"0x5"`; exports[`datatype > 1337 > json 1`] = `"{\\"foo\\":\\"U/4:SK$>6Q\\",\\"bar\\":2359372120326144,\\"bike\\":\\"{:e=+kD)[B\\",\\"a\\":\\"e|/Jqjjj!B\\",\\"b\\":\\"GDWQgC2M;q\\",\\"name\\":3648103756333056,\\"prop\\":\\"I1.Gm3tRwn\\"}"`; -exports[`datatype > 1337 > number > noArgs 1`] = `26202`; +exports[`datatype > 1337 > number > noArgs 1`] = `5048803172286464`; + +exports[`datatype > 1337 > number > noArgs 2`] = `0.21258764900267124`; + +exports[`datatype > 1337 > number > noArgs 3`] = `4891635882131456`; + +exports[`datatype > 1337 > number > noArgs 4`] = `NaN`; + +exports[`datatype > 1337 > number > noArgs 5`] = `0.3210005429573357`; + +exports[`datatype > 1337 > object > noArgs 1`] = `[]`; + +exports[`datatype > 1337 > object > noArgs 2`] = `2007-06-16T10:42:27.147Z`; + +exports[`datatype > 1337 > object > noArgs 3`] = `{}`; + +exports[`datatype > 1337 > object > noArgs 4`] = `[]`; + +exports[`datatype > 1337 > object > noArgs 5`] = `2040-07-10T23:23:28.285Z`; + +exports[`datatype > 1337 > string > noArgs 1`] = `"U/4:SK$>6Q"`; + +exports[`datatype > 1337 > string > noArgs 2`] = `""`; + +exports[`datatype > 1337 > string > noArgs 3`] = `"@{:e=+kD)["`; -exports[`datatype > 1337 > number > repeated 1`] = `1`; +exports[`datatype > 1337 > string > noArgs 4`] = `",e|/Jqjjj!"`; -exports[`datatype > 1337 > number > repeated 2`] = `3`; +exports[`datatype > 1337 > string > noArgs 5`] = `"LGDWQgC2M;"`; -exports[`datatype > 1337 > number > repeated 3`] = `1`; +exports[`datatype > 1337 > symbol > noArgs 1`] = `Symbol(DiloCxb)`; -exports[`datatype > 1337 > number > repeated 4`] = `1`; +exports[`datatype > 1337 > symbol > noArgs 2`] = `Symbol(mAEnrYoM)`; -exports[`datatype > 1337 > number > repeated 5`] = `1`; +exports[`datatype > 1337 > symbol > noArgs 3`] = `Symbol(fPueGsgM)`; -exports[`datatype > 1337 > number > with max 1`] = `18`; +exports[`datatype > 1337 > symbol > noArgs 4`] = `Symbol(ixSPPPasyvtEBNtjyoSI)`; -exports[`datatype > 1337 > number > with min 1`] = `26160`; +exports[`datatype > 1337 > symbol > noArgs 5`] = `Symbol(zwjhvQkUBW)`; -exports[`datatype > 1337 > number > with min and max 1`] = `-13`; +exports[`datatype > 1337 > undefined > noArgs 1`] = `undefined`; -exports[`datatype > 1337 > number > with min, max and precision 1`] = `-12.92`; +exports[`datatype > 1337 > undefined > noArgs 2`] = `undefined`; -exports[`datatype > 1337 > string > noArgs 1`] = `"9U/4:SK$>6"`; +exports[`datatype > 1337 > undefined > noArgs 3`] = `undefined`; -exports[`datatype > 1337 > string > with length option 1`] = `"9U/4:SK$>6QX9@{:e=+kD)"`; +exports[`datatype > 1337 > undefined > noArgs 4`] = `undefined`; -exports[`datatype > 1337 > string > with number 1`] = `"9U/4:SK$>6QX9@{:e=+kD)[B,e|/Jqjjj!BLGDWQgC"`; +exports[`datatype > 1337 > undefined > noArgs 5`] = `undefined`; exports[`datatype > 1337 > uuid 1`] = `"48234870-5389-445f-b4b4-1c61a52bf27d"`; diff --git a/test/__snapshots__/helpers.spec.ts.snap b/test/__snapshots__/helpers.spec.ts.snap index 64562da72e0..e555413ef8c 100644 --- a/test/__snapshots__/helpers.spec.ts.snap +++ b/test/__snapshots__/helpers.spec.ts.snap @@ -81,28 +81,28 @@ exports[`helpers > 42 > maybe > with value and probability 1`] = `undefined`; exports[`helpers > 42 > multiple > with method and count 1`] = ` [ - 37454, - 79654, - 95071, - 18343, - 73199, + 3373557438480384, + 7174621373661184, + 8563273238577152, + 1652233682812928, + 6593215255805952, ] `; exports[`helpers > 42 > multiple > with method and count range 1`] = ` [ - 79654, - 95071, - 18343, - 73199, + 7174621373661184, + 8563273238577152, + 1652233682812928, + 6593215255805952, ] `; exports[`helpers > 42 > multiple > with only method 1`] = ` [ - 37454, - 79654, - 95071, + 3373557438480384, + 7174621373661184, + 8563273238577152, ] `; @@ -308,34 +308,34 @@ exports[`helpers > 1211 > maybe > with value and probability 1`] = `undefined`; exports[`helpers > 1211 > multiple > with method and count 1`] = ` [ - 92852, - 45901, - 89347, - 77826, - 22557, + 8363366036799488, + 4134441414819840, + 8047677172350976, + 7010029022478336, + 2031760839802880, ] `; exports[`helpers > 1211 > multiple > with method and count range 1`] = ` [ - 45901, - 89347, - 77826, - 22557, - 12988, - 99725, - 3842, - 67199, - 15897, - 68481, + 4134441414819840, + 8047677172350976, + 7010029022478336, + 2031760839802880, + 1169939440336896, + 8982492805595136, + 346135076012032, + 6052754548064256, + 1431911878623232, + 6168278875504640, ] `; exports[`helpers > 1211 > multiple > with only method 1`] = ` [ - 92852, - 45901, - 89347, + 8363366036799488, + 4134441414819840, + 8047677172350976, ] `; @@ -530,27 +530,27 @@ exports[`helpers > 1337 > maybe > with value and probability 1`] = `undefined`; exports[`helpers > 1337 > multiple > with method and count 1`] = ` [ - 26202, - 56052, - 15868, - 21258, - 27812, + 2360108468142080, + 5048803172286464, + 1429298200182784, + 1914819313664000, + 2505140957347840, ] `; exports[`helpers > 1337 > multiple > with method and count range 1`] = ` [ - 56052, - 15868, - 21258, + 5048803172286464, + 1429298200182784, + 1914819313664000, ] `; exports[`helpers > 1337 > multiple > with only method 1`] = ` [ - 26202, - 56052, - 15868, + 2360108468142080, + 5048803172286464, + 1429298200182784, ] `; diff --git a/test/all_functional.spec.ts b/test/all_functional.spec.ts index 25619c9e774..7f62b14f00a 100644 --- a/test/all_functional.spec.ts +++ b/test/all_functional.spec.ts @@ -6,6 +6,8 @@ const IGNORED_MODULES = [ 'rawDefinitions', 'definitions', 'helpers', + // The `datatype` return values are considered invalid for most other methods + 'datatype', '_mersenne', '_defaultRefDate', ]; diff --git a/test/datatype.spec.ts b/test/datatype.spec.ts index 2c09ea05a10..ae69eb91edd 100644 --- a/test/datatype.spec.ts +++ b/test/datatype.spec.ts @@ -6,22 +6,28 @@ const NON_SEEDED_BASED_RUN = 25; describe('datatype', () => { seededTests(faker, 'datatype', (t) => { - t.describe('number', (t) => { - t.it('noArgs') - .itRepeated('repeated', 5, 6) - .it('with min', { min: -42 }) - .it('with max', { max: 69 }) - .it('with min and max', { - min: -42, - max: 69, - }) - .it('with min, max and precision', { - min: -42, - max: 69, - precision: 0.01, + t.describeEach( + 'bigint', + 'function', + 'number', + 'object', + 'string', + 'symbol', + 'undefined' + )((t) => { + t.itRepeated('noArgs', 5); + }); + + t.describe('boolean', (t) => { + t.itRepeated('noArgs', 5) + .it('with probability', 0.42) + .it('with probability option', { + probability: 0.13, }); }); + // Deprecated methods + t.describe('float', (t) => { t.it('noArgs') .itRepeated('repeated', 6) @@ -50,20 +56,8 @@ describe('datatype', () => { }); }); - t.describe('string', (t) => { - t.it('noArgs') - .it('with number', 42) - .it('with length option', { length: 22 }); - }); - t.itRepeated('uuid', 5); - t.describe('boolean', (t) => { - t.itRepeated('noArgs', 5) - .it('with probability', 0.42) - .it('with probability option', { probability: 0.13 }); - }); - t.describe('hexadecimal', (t) => { t.it('noArgs') .it('with length', { length: 42 }) @@ -91,145 +85,77 @@ describe('datatype', () => { describe(`random seeded tests for seed ${faker.seed()}`, () => { for (let i = 1; i <= NON_SEEDED_BASED_RUN; i++) { - describe('number', () => { - it('should return a random number given a maximum value as Number', () => { - const max = 10; - - const actual = faker.datatype.number(max); - - expect(actual).toBeGreaterThanOrEqual(0); - expect(actual).toBeLessThanOrEqual(max); + describe.each([ + 'bigint', + 'boolean', + 'function', + 'number', + 'object', + 'string', + 'symbol', + 'undefined', + ] as const)('%s', (type) => { + it(`should return a value that will result in \`true\` when checked against JavaScript's \`typeof value === '${type}'\` operator`, () => { + const actual = faker.datatype[type](); + expect(actual).toBeTypeOf(type); }); + }); - it('should return a random number given a maximum value as Object', () => { - const options = { max: 10 }; - - const actual = faker.datatype.number(options); - - expect(actual).toBeGreaterThanOrEqual(0); - expect(actual).toBeLessThanOrEqual(options.max); - }); - - it('should return a random number given a maximum value of 0', () => { - const options = { max: 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 }; - - const actual = faker.datatype.number(options); - - expect(actual).toBeGreaterThanOrEqual(options.min); - expect(actual).toBeLessThanOrEqual(options.max); + describe('boolean', () => { + it('generates false for probability = 0', () => { + const bool = faker.datatype.boolean(0); + expect(bool).toBe(false); }); - it('should return a random number between a range', () => { - const options = { min: 22, max: 33 }; - for (let i = 0; i < 100; i++) { - const actual = faker.datatype.number(options); - expect(actual).toBeGreaterThanOrEqual(options.min); - expect(actual).toBeLessThanOrEqual(options.max); - } + it('generates true for probability = 1', () => { + const bool = faker.datatype.boolean(1); + expect(bool).toBe(true); }); - 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).toBeGreaterThanOrEqual(-5); - expect(actual).toBeLessThanOrEqual(-4); - - if (foundNegative4 && foundNegative5) { - break; - } + it.each([-5, 0.42, 5])( + 'generates a boolean value with given probability', + (probability) => { + const bool = faker.datatype.boolean(probability); + expect(bool).toBeTypeOf('boolean'); } + ); - expect(foundNegative4).toBeTruthy(); - expect(foundNegative5).toBeTruthy(); + it('generates a boolean value for empty options', () => { + const bool = faker.datatype.boolean({}); + expect(bool).toBeTypeOf('boolean'); }); - it('provides numbers with a given precision of 0.5 steps', () => { - const results = Array.from( - new Set( - Array.from({ length: 50 }, () => - faker.datatype.float({ - min: 0, - max: 1.5, - precision: 0.5, - }) - ) - ) - ).sort(); - - expect(results).toEqual([0, 0.5, 1, 1.5]); + it('generates false for { probability: 0 }', () => { + const bool = faker.datatype.boolean({ probability: 0 }); + expect(bool).toBe(false); }); - // TODO @Shinigami92 2022-11-24: https://github.com/faker-js/faker/issues/1595 - it.todo('provides numbers with a given precision of 0.4 steps', () => { - const results = Array.from( - new Set( - Array.from({ length: 50 }, () => - faker.datatype.float({ - min: 0, - max: 1.9, - precision: 0.4, - }) - ) - ) - ).sort(); - - expect(results).toEqual([0, 0.4, 0.8, 1.2, 1.6]); + it('generates true for { probability: 1 }', () => { + const bool = faker.datatype.boolean({ probability: 1 }); + expect(bool).toBe(true); }); - 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 actual = faker.datatype.number(options); - expect(actual).toBe(Number(actual.toFixed(2))); + it.each([-5, 0.42, 5])( + 'generates a boolean value with given probability option', + (probability) => { + const bool = faker.datatype.boolean({ probability }); + expect(bool).toBeTypeOf('boolean'); } - }); + ); it('should not mutate the input object', () => { - const initialMin = 1; - const initialPrecision = 1; - const initialOtherProperty = 'hello darkness my old friend'; - const input: { - min?: number; - max?: number; - precision?: number; - otherProperty: string; - } = Object.freeze({ - min: initialMin, - precision: initialPrecision, - otherProperty: initialOtherProperty, + const filledOptions: { probability?: number } = Object.freeze({ + probability: 1, }); + expect(() => faker.datatype.boolean(filledOptions)).not.toThrow(); - expect(() => faker.datatype.number(input)).not.toThrow(); - }); - - it('should throw when min > max', () => { - const min = 10; - const max = 9; - - expect(() => { - faker.datatype.number({ min, max }); - }).toThrowError(`Max ${max} should be greater than min ${min}.`); + const emptyOptions: { probability?: number } = Object.freeze({}); + expect(() => faker.datatype.boolean(emptyOptions)).not.toThrow(); }); }); + // Deprecated methods + describe('float', () => { it('should return a random float with a default precision value (0.01)', () => { const number = faker.datatype.float(); @@ -313,85 +239,6 @@ describe('datatype', () => { }); }); - describe('string', () => { - it('should generate a string value', () => { - const generatedString = faker.datatype.string(); - expect(generatedString).toBeTypeOf('string'); - expect(generatedString).toHaveLength(10); - }); - - it('should return empty string if negative length is passed', () => { - const negativeValue = faker.datatype.number({ min: -1000, max: -1 }); - const generatedString = faker.datatype.string(negativeValue); - expect(generatedString).toBe(''); - expect(generatedString).toHaveLength(0); - }); - - it('should return string with length of 2^20 if bigger length value is passed', () => { - const overMaxValue = Math.pow(2, 28); - const generatedString = faker.datatype.string(overMaxValue); - expect(generatedString).toHaveLength(Math.pow(2, 20)); - }); - }); - - describe('boolean', () => { - it('generates a boolean value', () => { - const bool = faker.datatype.boolean(); - expect(bool).toBeTypeOf('boolean'); - }); - - it('generates false for probability = 0', () => { - const bool = faker.datatype.boolean(0); - expect(bool).toBe(false); - }); - - it('generates true for probability = 1', () => { - const bool = faker.datatype.boolean(1); - expect(bool).toBe(true); - }); - - it.each([-5, 0.42, 5])( - 'generates a boolean value with given probability', - (probability) => { - const bool = faker.datatype.boolean(probability); - expect(bool).toBeTypeOf('boolean'); - } - ); - - it('generates a boolean value for empty options', () => { - const bool = faker.datatype.boolean({}); - expect(bool).toBeTypeOf('boolean'); - }); - - it('generates false for { probability: 0 }', () => { - const bool = faker.datatype.boolean({ probability: 0 }); - expect(bool).toBe(false); - }); - - it('generates true for { probability: 1 }', () => { - const bool = faker.datatype.boolean({ probability: 1 }); - expect(bool).toBe(true); - }); - - it.each([-5, 0.42, 5])( - 'generates a boolean value with given probability option', - (probability) => { - const bool = faker.datatype.boolean({ probability }); - expect(bool).toBeTypeOf('boolean'); - } - ); - - it('should not mutate the input object', () => { - const filledOptions: { probability?: number } = Object.freeze({ - probability: 1, - }); - expect(() => faker.datatype.boolean(filledOptions)).not.toThrow(); - - const emptyOptions: { probability?: number } = Object.freeze({}); - expect(() => faker.datatype.boolean(emptyOptions)).not.toThrow(); - }); - }); - describe('UUID', () => { it('generates a valid UUID', () => { const UUID = faker.datatype.uuid(); @@ -447,7 +294,7 @@ describe('datatype', () => { describe('array', () => { it('generates an array with passed size', () => { - const randomSize = faker.datatype.number(); + const randomSize = faker.number.int(1000); const generatedArray = faker.datatype.array(randomSize); expect(generatedArray).toHaveLength(randomSize); }); diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts index 2dcb64aafb7..5255529f56b 100644 --- a/test/helpers.spec.ts +++ b/test/helpers.spec.ts @@ -181,9 +181,9 @@ describe('helpers', () => { }); t.describe('multiple', (t) => { - t.it('with only method', faker.datatype.number) - .it('with method and count', faker.datatype.number, { count: 5 }) - .it('with method and count range', faker.datatype.number, { + t.it('with only method', faker.number.int) + .it('with method and count', faker.number.int, { count: 5 }) + .it('with method and count range', faker.number.int, { count: { min: 1, max: 10 }, }); });