From a1a587c57355ca5ccdb2fcd2dfba7c3e699413fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leyla=20J=C3=A4hnig?= Date: Thu, 17 Feb 2022 19:54:59 +0100 Subject: [PATCH 1/8] feat: add random.objectKey and random.objectValue --- src/random.ts | 56 +++++++++++++++++++++++++++++++++++++++++++-- test/random.spec.ts | 26 +++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/src/random.ts b/src/random.ts index c349c92fab4..7e5f1846c9c 100644 --- a/src/random.ts +++ b/src/random.ts @@ -170,11 +170,16 @@ export class Random { * If this is set to `'value'`, this method will a return a random value of the given instance. * Defaults to `'value'`. * + * @see faker.random.objectKey() + * @see faker.random.objectValue() + * * @example * const object = { keyA: 'valueA', keyB: 42 }; * faker.random.objectElement(object) // 42 * faker.random.objectElement(object, 'key') // 'keyB' * faker.random.objectElement(object, 'value') // 'valueA' + * + * @deprecated */ objectElement, K extends keyof T>( object: T, @@ -184,6 +189,7 @@ export class Random { object: T, field?: unknown ): T[K]; + // For typedoc/api docs /** * Returns a random key or value from given object. * @@ -194,11 +200,16 @@ export class Random { * If this is set to `'value'`, this method will a return a random value of the given instance. * Defaults to `'value'`. * + * @see faker.random.objectKey() + * @see faker.random.objectValue() + * * @example * const object = { keyA: 'valueA', keyB: 42 }; * faker.random.objectElement(object) // 42 * faker.random.objectElement(object, 'key') // 'keyB' * faker.random.objectElement(object, 'value') // 'valueA' + * + * @deprecated */ objectElement, K extends keyof T>( object: T, @@ -208,10 +219,51 @@ export class Random { object = { foo: 'bar', too: 'car' } as unknown as T, field = 'value' ): K | T[K] { + deprecated({ + deprecated: 'faker.random.objectElement()', + proposed: 'faker.random.objectKey() or faker.random.objectValue()', + since: 'v6.3.0', + until: 'v7.0.0', + }); + return field === 'key' + ? (this.faker.random.objectKey(object) as K) + : (this.faker.random.objectValue(object) as T[K]); + } + + /** + * Returns a random key from given object. + * + * @param object The optional object to be used. If not specified, it defaults to `{ foo: 'bar', too: 'car' }`. + * + * @example + * faker.random.objectKey() // 'foo' + * faker.random.objectKey({ myProperty: 'myValue' }) // 'myProperty' + */ + objectKey>( + object: T = { foo: 'bar', too: 'car' } as unknown as T + ): keyof T { const array: Array = Object.keys(object); - const key = this.arrayElement(array); + const key = this.faker.random.arrayElement(array); + + return key; + } + + /** + * Returns a random value from given object. + * + * @param object The optional object to be used. If not specified, it defaults to `{ foo: 'bar', too: 'car' }`. + * + * @example + * faker.random.objectValue() // 'bar' + * faker.random.objectValue({ myProperty: 'myValue' }) // 'myValue' + */ + objectValue>( + object: T = { foo: 'bar', too: 'car' } as unknown as T + ): T[keyof T] { + const key = this.faker.random.objectKey(object); + const value = object[key]; - return field === 'key' ? (key as K) : (object[key] as T[K]); + return value; } /** diff --git a/test/random.spec.ts b/test/random.spec.ts index f3a47d87414..cce835cbd6f 100644 --- a/test/random.spec.ts +++ b/test/random.spec.ts @@ -181,6 +181,32 @@ describe('random', () => { }); }); + describe('objectKey', () => { + it('should return a random key', () => { + const testObject = { + hello: 'to', + you: 'my', + friend: '!', + }; + const actual = faker.random.objectKey(testObject); + + expect(Object.keys(testObject)).toContain(actual); + }); + }); + + describe('objectValue', () => { + it('should return a random value', () => { + const testObject = { + hello: 'to', + you: 'my', + friend: '!', + }; + const actual = faker.random.objectValue(testObject); + + expect(Object.values(testObject)).toContain(actual); + }); + }); + describe('word', () => { const bannedChars = [ '!', From e4482076e929b5f9b18dd6ca0503b73f4416d98a Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Fri, 29 Apr 2022 13:17:28 +0200 Subject: [PATCH 2/8] chore: fix jsdoc --- src/random.ts | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/random.ts b/src/random.ts index 7e5f1846c9c..9a0845b0ecc 100644 --- a/src/random.ts +++ b/src/random.ts @@ -161,23 +161,18 @@ export class Random { } /** - * Returns a random key or value from given object. + * Returns a random key from given object. * * @template T The type of `Record` to pick from. * @template K The keys of `T`. - * @param object The object to get the keys or values from. + * @param object The object to get the keys from. * @param field If this is set to `'key'`, this method will a return a random key of the given instance. - * If this is set to `'value'`, this method will a return a random value of the given instance. - * Defaults to `'value'`. * * @see faker.random.objectKey() - * @see faker.random.objectValue() * * @example * const object = { keyA: 'valueA', keyB: 42 }; - * faker.random.objectElement(object) // 42 * faker.random.objectElement(object, 'key') // 'keyB' - * faker.random.objectElement(object, 'value') // 'valueA' * * @deprecated */ @@ -185,6 +180,23 @@ export class Random { object: T, field: 'key' ): K; + /** + * Returns a random value from given object. + * + * @template T The type of `Record` to pick from. + * @template K The keys of `T`. + * @param object The object to get the values from. + * @param field If this is set to `'value'`, this method will a return a random value of the given instance. + * + * @see faker.random.objectValue() + * + * @example + * const object = { keyA: 'valueA', keyB: 42 }; + * faker.random.objectElement(object) // 42 + * faker.random.objectElement(object, 'value') // 'valueA' + * + * @deprecated + */ objectElement, K extends keyof T>( object: T, field?: unknown @@ -212,12 +224,8 @@ export class Random { * @deprecated */ objectElement, K extends keyof T>( - object: T, - field?: 'key' | 'value' - ): K | T[K]; - objectElement, K extends keyof T>( - object = { foo: 'bar', too: 'car' } as unknown as T, - field = 'value' + object: T = { foo: 'bar', too: 'car' } as unknown as T, + field: 'key' | 'value' = 'value' ): K | T[K] { deprecated({ deprecated: 'faker.random.objectElement()', From 9302a95d6bd1ec94f115b37bc83071d038a94a15 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Fri, 29 Apr 2022 13:23:25 +0200 Subject: [PATCH 3/8] chore: enhance deprecation message --- src/random.ts | 5 +++-- test/random.spec.ts | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/random.ts b/src/random.ts index 9a0845b0ecc..885ed87d96a 100644 --- a/src/random.ts +++ b/src/random.ts @@ -227,9 +227,10 @@ export class Random { object: T = { foo: 'bar', too: 'car' } as unknown as T, field: 'key' | 'value' = 'value' ): K | T[K] { + const useKey = field === 'key'; deprecated({ - deprecated: 'faker.random.objectElement()', - proposed: 'faker.random.objectKey() or faker.random.objectValue()', + deprecated: `faker.random.objectElement(${useKey ? "obj, 'key'" : ''})`, + proposed: `faker.random.object${useKey ? 'Key' : 'Value'}()`, since: 'v6.3.0', until: 'v7.0.0', }); diff --git a/test/random.spec.ts b/test/random.spec.ts index cce835cbd6f..568b7a5a83e 100644 --- a/test/random.spec.ts +++ b/test/random.spec.ts @@ -159,6 +159,8 @@ describe('random', () => { describe('objectElement', () => { it('should return a random value', () => { + const spy = vi.spyOn(console, 'warn'); + const testObject = { hello: 'to', you: 'my', @@ -167,9 +169,16 @@ describe('random', () => { const actual = faker.random.objectElement(testObject); expect(Object.values(testObject)).toContain(actual); + expect(spy).toHaveBeenCalledWith( + `[@faker-js/faker]: faker.random.objectElement() is deprecated since v6.3.0 and will be removed in v7.0.0. Please use faker.random.objectValue() instead.` + ); + + spy.mockRestore(); }); it('should return a random key', () => { + const spy = vi.spyOn(console, 'warn'); + const testObject = { hello: 'to', you: 'my', @@ -178,6 +187,11 @@ describe('random', () => { const actual = faker.random.objectElement(testObject, 'key'); expect(Object.keys(testObject)).toContain(actual); + expect(spy).toHaveBeenCalledWith( + `[@faker-js/faker]: faker.random.objectElement(obj, 'key') is deprecated since v6.3.0 and will be removed in v7.0.0. Please use faker.random.objectKey() instead.` + ); + + spy.mockRestore(); }); }); From bef137d44fa909dd2a567df2467dc3d258b61437 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Fri, 29 Apr 2022 14:16:31 +0200 Subject: [PATCH 4/8] chore: use new functions --- src/finance.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/finance.ts b/src/finance.ts index 2214088dc76..0aeefaa4b74 100644 --- a/src/finance.ts +++ b/src/finance.ts @@ -171,7 +171,7 @@ export class Finance { * faker.finance.currencyCode() // 'USD' */ currencyCode(): string { - return this.faker.random.objectElement( + return this.faker.random.objectValue( this.faker.definitions.finance.currency )['code']; } @@ -183,10 +183,9 @@ export class Finance { * faker.finance.currencyName() // 'US Dollar' */ currencyName(): string { - return this.faker.random.objectElement( - this.faker.definitions.finance.currency, - 'key' - ); + return this.faker.random.objectKey( + this.faker.definitions.finance.currency + ) as string; } /** @@ -198,7 +197,7 @@ export class Finance { currencySymbol(): string { let symbol: string; while (!symbol) { - symbol = this.faker.random.objectElement( + symbol = this.faker.random.objectValue( this.faker.definitions.finance.currency )['symbol']; } @@ -265,7 +264,7 @@ export class Finance { } else { // Choose a random provider // Credit cards are in an object structure - const formats = this.faker.random.objectElement(localeFormat, 'value'); // There could be multiple formats + const formats = this.faker.random.objectValue(localeFormat); // There could be multiple formats format = this.faker.random.arrayElement(formats); } format = format.replace(/\//g, ''); From 57a164f60aa349fcd4a97ce2d47cb679c938973a Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Fri, 29 Apr 2022 14:48:30 +0200 Subject: [PATCH 5/8] chore: add jsdoc back for api-docs --- src/random.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/random.ts b/src/random.ts index 885ed87d96a..8f75da0aa31 100644 --- a/src/random.ts +++ b/src/random.ts @@ -201,7 +201,31 @@ export class Random { object: T, field?: unknown ): T[K]; - // For typedoc/api docs + /** + * Returns a random key or value from given object. + * + * @template T The type of `Record` to pick from. + * @template K The keys of `T`. + * @param object The object to get the keys or values from. + * @param field If this is set to `'key'`, this method will a return a random key of the given instance. + * If this is set to `'value'`, this method will a return a random value of the given instance. + * Defaults to `'value'`. + * + * @see faker.random.objectKey() + * @see faker.random.objectValue() + * + * @example + * const object = { keyA: 'valueA', keyB: 42 }; + * faker.random.objectElement(object) // 42 + * faker.random.objectElement(object, 'key') // 'keyB' + * faker.random.objectElement(object, 'value') // 'valueA' + * + * @deprecated + */ + objectElement, K extends keyof T>( + object?: T, + field?: 'key' | 'value' + ): K | T[K]; /** * Returns a random key or value from given object. * From 9cb89d772bca1f999de0666b7a5b07a9451656fe Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Fri, 29 Apr 2022 15:16:10 +0200 Subject: [PATCH 6/8] chore: apply suggestions --- src/random.ts | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/random.ts b/src/random.ts index 8f75da0aa31..9969df72a3b 100644 --- a/src/random.ts +++ b/src/random.ts @@ -266,37 +266,27 @@ export class Random { /** * Returns a random key from given object. * - * @param object The optional object to be used. If not specified, it defaults to `{ foo: 'bar', too: 'car' }`. + * @param object The object to be used. * * @example - * faker.random.objectKey() // 'foo' * faker.random.objectKey({ myProperty: 'myValue' }) // 'myProperty' */ - objectKey>( - object: T = { foo: 'bar', too: 'car' } as unknown as T - ): keyof T { + objectKey>(object: T): keyof T { const array: Array = Object.keys(object); - const key = this.faker.random.arrayElement(array); - - return key; + return this.faker.random.arrayElement(array); } /** * Returns a random value from given object. * - * @param object The optional object to be used. If not specified, it defaults to `{ foo: 'bar', too: 'car' }`. + * @param object The object to be used. * * @example - * faker.random.objectValue() // 'bar' * faker.random.objectValue({ myProperty: 'myValue' }) // 'myValue' */ - objectValue>( - object: T = { foo: 'bar', too: 'car' } as unknown as T - ): T[keyof T] { + objectValue>(object: T): T[keyof T] { const key = this.faker.random.objectKey(object); - const value = object[key]; - - return value; + return object[key]; } /** From 3d7c307f40616f81d56a3e2c863a9459c7ca8b77 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Fri, 29 Apr 2022 15:23:23 +0200 Subject: [PATCH 7/8] chore: move to helpers --- src/finance.ts | 8 ++++---- src/helpers.ts | 32 +++++++++++++++++++++++++++++--- src/random.ts | 32 +++----------------------------- test/helpers.spec.ts | 26 ++++++++++++++++++++++++++ test/random.spec.ts | 30 ++---------------------------- 5 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/finance.ts b/src/finance.ts index 0aeefaa4b74..1ff24ecad10 100644 --- a/src/finance.ts +++ b/src/finance.ts @@ -171,7 +171,7 @@ export class Finance { * faker.finance.currencyCode() // 'USD' */ currencyCode(): string { - return this.faker.random.objectValue( + return this.faker.helpers.objectValue( this.faker.definitions.finance.currency )['code']; } @@ -183,7 +183,7 @@ export class Finance { * faker.finance.currencyName() // 'US Dollar' */ currencyName(): string { - return this.faker.random.objectKey( + return this.faker.helpers.objectKey( this.faker.definitions.finance.currency ) as string; } @@ -197,7 +197,7 @@ export class Finance { currencySymbol(): string { let symbol: string; while (!symbol) { - symbol = this.faker.random.objectValue( + symbol = this.faker.helpers.objectValue( this.faker.definitions.finance.currency )['symbol']; } @@ -264,7 +264,7 @@ export class Finance { } else { // Choose a random provider // Credit cards are in an object structure - const formats = this.faker.random.objectValue(localeFormat); // There could be multiple formats + const formats = this.faker.helpers.objectValue(localeFormat); // There could be multiple formats format = this.faker.random.arrayElement(formats); } format = format.replace(/\//g, ''); diff --git a/src/helpers.ts b/src/helpers.ts index 5ca332d475d..5aec537c9f2 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -701,9 +701,9 @@ export class Helpers { * @param options.probability The probability (`[0.00, 1.00]`) of the callback being invoked. Defaults to `0.5`. * * @example - * faker.random.maybe(() => 'Hello World!') // 'Hello World!' - * faker.random.maybe(() => 'Hello World!', { probability: 0.1 }) // undefined - * faker.random.maybe(() => 'Hello World!', { probability: 0.9 }) // 'Hello World!' + * faker.helpers.maybe(() => 'Hello World!') // 'Hello World!' + * faker.helpers.maybe(() => 'Hello World!', { probability: 0.1 }) // undefined + * faker.helpers.maybe(() => 'Hello World!', { probability: 0.9 }) // 'Hello World!' */ maybe( callback: () => T, @@ -715,4 +715,30 @@ export class Helpers { } return undefined; } + + /** + * Returns a random key from given object. + * + * @param object The object to be used. + * + * @example + * faker.helpers.objectKey({ myProperty: 'myValue' }) // 'myProperty' + */ + objectKey>(object: T): keyof T { + const array: Array = Object.keys(object); + return this.faker.random.arrayElement(array); + } + + /** + * Returns a random value from given object. + * + * @param object The object to be used. + * + * @example + * faker.helpers.objectValue({ myProperty: 'myValue' }) // 'myValue' + */ + objectValue>(object: T): T[keyof T] { + const key = this.faker.helpers.objectKey(object); + return object[key]; + } } diff --git a/src/random.ts b/src/random.ts index 9969df72a3b..6fb74d1d5fc 100644 --- a/src/random.ts +++ b/src/random.ts @@ -254,39 +254,13 @@ export class Random { const useKey = field === 'key'; deprecated({ deprecated: `faker.random.objectElement(${useKey ? "obj, 'key'" : ''})`, - proposed: `faker.random.object${useKey ? 'Key' : 'Value'}()`, + proposed: `faker.helpers.object${useKey ? 'Key' : 'Value'}()`, since: 'v6.3.0', until: 'v7.0.0', }); return field === 'key' - ? (this.faker.random.objectKey(object) as K) - : (this.faker.random.objectValue(object) as T[K]); - } - - /** - * Returns a random key from given object. - * - * @param object The object to be used. - * - * @example - * faker.random.objectKey({ myProperty: 'myValue' }) // 'myProperty' - */ - objectKey>(object: T): keyof T { - const array: Array = Object.keys(object); - return this.faker.random.arrayElement(array); - } - - /** - * Returns a random value from given object. - * - * @param object The object to be used. - * - * @example - * faker.random.objectValue({ myProperty: 'myValue' }) // 'myValue' - */ - objectValue>(object: T): T[keyof T] { - const key = this.faker.random.objectKey(object); - return object[key]; + ? (this.faker.helpers.objectKey(object) as K) + : (this.faker.helpers.objectValue(object) as T[K]); } /** diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts index 5ee4b2a7c53..3f63a80728c 100644 --- a/test/helpers.spec.ts +++ b/test/helpers.spec.ts @@ -831,6 +831,32 @@ describe('helpers', () => { }); }); + describe('objectKey', () => { + it('should return a random key', () => { + const testObject = { + hello: 'to', + you: 'my', + friend: '!', + }; + const actual = faker.helpers.objectKey(testObject); + + expect(Object.keys(testObject)).toContain(actual); + }); + }); + + describe('objectValue', () => { + it('should return a random value', () => { + const testObject = { + hello: 'to', + you: 'my', + friend: '!', + }; + const actual = faker.helpers.objectValue(testObject); + + expect(Object.values(testObject)).toContain(actual); + }); + }); + describe('deprecation warnings', () => { it.each([['randomize', 'random.arrayElement']])( 'should warn user that function helpers.%s is deprecated', diff --git a/test/random.spec.ts b/test/random.spec.ts index 568b7a5a83e..a3c93562aea 100644 --- a/test/random.spec.ts +++ b/test/random.spec.ts @@ -170,7 +170,7 @@ describe('random', () => { expect(Object.values(testObject)).toContain(actual); expect(spy).toHaveBeenCalledWith( - `[@faker-js/faker]: faker.random.objectElement() is deprecated since v6.3.0 and will be removed in v7.0.0. Please use faker.random.objectValue() instead.` + `[@faker-js/faker]: faker.random.objectElement() is deprecated since v6.3.0 and will be removed in v7.0.0. Please use faker.helpers.objectValue() instead.` ); spy.mockRestore(); @@ -188,39 +188,13 @@ describe('random', () => { expect(Object.keys(testObject)).toContain(actual); expect(spy).toHaveBeenCalledWith( - `[@faker-js/faker]: faker.random.objectElement(obj, 'key') is deprecated since v6.3.0 and will be removed in v7.0.0. Please use faker.random.objectKey() instead.` + `[@faker-js/faker]: faker.random.objectElement(obj, 'key') is deprecated since v6.3.0 and will be removed in v7.0.0. Please use faker.helpers.objectKey() instead.` ); spy.mockRestore(); }); }); - describe('objectKey', () => { - it('should return a random key', () => { - const testObject = { - hello: 'to', - you: 'my', - friend: '!', - }; - const actual = faker.random.objectKey(testObject); - - expect(Object.keys(testObject)).toContain(actual); - }); - }); - - describe('objectValue', () => { - it('should return a random value', () => { - const testObject = { - hello: 'to', - you: 'my', - friend: '!', - }; - const actual = faker.random.objectValue(testObject); - - expect(Object.values(testObject)).toContain(actual); - }); - }); - describe('word', () => { const bannedChars = [ '!', From 256739653de6479e109c68a320d0bca69501d026 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Fri, 29 Apr 2022 17:47:04 +0200 Subject: [PATCH 8/8] chore: update jsdocs --- src/helpers.ts | 3 ++- src/random.ts | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/helpers.ts b/src/helpers.ts index 5aec537c9f2..a04c577929f 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -112,7 +112,8 @@ export interface Transaction { } /** - * Module with various helper methods that don't fit in a particular category. + * Module with various helper methods that transform the method input rather than returning values from locales. + * The transformation process may call methods that use the locale data. */ export class Helpers { constructor(private readonly faker: Faker) { diff --git a/src/random.ts b/src/random.ts index 6fb74d1d5fc..2b90db073f7 100644 --- a/src/random.ts +++ b/src/random.ts @@ -168,7 +168,7 @@ export class Random { * @param object The object to get the keys from. * @param field If this is set to `'key'`, this method will a return a random key of the given instance. * - * @see faker.random.objectKey() + * @see faker.helpers.objectKey() * * @example * const object = { keyA: 'valueA', keyB: 42 }; @@ -188,7 +188,7 @@ export class Random { * @param object The object to get the values from. * @param field If this is set to `'value'`, this method will a return a random value of the given instance. * - * @see faker.random.objectValue() + * @see faker.helpers.objectValue() * * @example * const object = { keyA: 'valueA', keyB: 42 }; @@ -211,8 +211,8 @@ export class Random { * If this is set to `'value'`, this method will a return a random value of the given instance. * Defaults to `'value'`. * - * @see faker.random.objectKey() - * @see faker.random.objectValue() + * @see faker.helpers.objectKey() + * @see faker.helpers.objectValue() * * @example * const object = { keyA: 'valueA', keyB: 42 }; @@ -236,8 +236,8 @@ export class Random { * If this is set to `'value'`, this method will a return a random value of the given instance. * Defaults to `'value'`. * - * @see faker.random.objectKey() - * @see faker.random.objectValue() + * @see faker.helpers.objectKey() + * @see faker.helpers.objectValue() * * @example * const object = { keyA: 'valueA', keyB: 42 };