Skip to content

Commit

Permalink
feat: separate methods for object key value (#503)
Browse files Browse the repository at this point in the history
Co-authored-by: Leyla Jähnig <leyla.jaehnig@outlook.de>
Co-authored-by: Shinigami92 <chrissi92@hotmail.de>
  • Loading branch information
3 people committed Apr 30, 2022
1 parent 6cfd1e1 commit 36cd461
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 24 deletions.
13 changes: 6 additions & 7 deletions src/finance.ts
Expand Up @@ -171,7 +171,7 @@ export class Finance {
* faker.finance.currencyCode() // 'USD'
*/
currencyCode(): string {
return this.faker.random.objectElement(
return this.faker.helpers.objectValue(
this.faker.definitions.finance.currency
)['code'];
}
Expand All @@ -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.helpers.objectKey(
this.faker.definitions.finance.currency
) as string;
}

/**
Expand All @@ -198,7 +197,7 @@ export class Finance {
currencySymbol(): string {
let symbol: string;
while (!symbol) {
symbol = this.faker.random.objectElement(
symbol = this.faker.helpers.objectValue(
this.faker.definitions.finance.currency
)['symbol'];
}
Expand Down Expand Up @@ -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.helpers.objectValue(localeFormat); // There could be multiple formats
format = this.faker.random.arrayElement(formats);
}
format = format.replace(/\//g, '');
Expand Down
35 changes: 31 additions & 4 deletions src/helpers.ts
Expand Up @@ -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) {
Expand Down Expand Up @@ -701,9 +702,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<T>(
callback: () => T,
Expand All @@ -715,4 +716,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<T extends Record<string, unknown>>(object: T): keyof T {
const array: Array<keyof T> = 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<T extends Record<string, unknown>>(object: T): T[keyof T] {
const key = this.faker.helpers.objectKey(object);
return object[key];
}
}
75 changes: 62 additions & 13 deletions src/random.ts
Expand Up @@ -161,25 +161,42 @@ 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.helpers.objectKey()
*
* @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<T extends Record<string, unknown>, K extends keyof T>(
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.helpers.objectValue()
*
* @example
* const object = { keyA: 'valueA', keyB: 42 };
* faker.random.objectElement(object) // 42
* faker.random.objectElement(object, 'value') // 'valueA'
*
* @deprecated
*/
objectElement<T extends Record<string, unknown>, K extends keyof T>(
object: T,
field?: unknown
Expand All @@ -194,24 +211,56 @@ 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.helpers.objectKey()
* @see faker.helpers.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<T extends Record<string, unknown>, K extends keyof T>(
object: T,
object?: T,
field?: 'key' | 'value'
): K | T[K];
/**
* 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.helpers.objectKey()
* @see faker.helpers.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<T extends Record<string, unknown>, 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] {
const array: Array<keyof T> = Object.keys(object);
const key = this.arrayElement(array);

return field === 'key' ? (key as K) : (object[key] as T[K]);
const useKey = field === 'key';
deprecated({
deprecated: `faker.random.objectElement(${useKey ? "obj, 'key'" : ''})`,
proposed: `faker.helpers.object${useKey ? 'Key' : 'Value'}()`,
since: 'v6.3.0',
until: 'v7.0.0',
});
return field === 'key'
? (this.faker.helpers.objectKey(object) as K)
: (this.faker.helpers.objectValue(object) as T[K]);
}

/**
Expand Down
26 changes: 26 additions & 0 deletions test/helpers.spec.ts
Expand Up @@ -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',
Expand Down
14 changes: 14 additions & 0 deletions test/random.spec.ts
Expand Up @@ -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',
Expand All @@ -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.helpers.objectValue() instead.`
);

spy.mockRestore();
});

it('should return a random key', () => {
const spy = vi.spyOn(console, 'warn');

const testObject = {
hello: 'to',
you: 'my',
Expand All @@ -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.helpers.objectKey() instead.`
);

spy.mockRestore();
});
});

Expand Down

0 comments on commit 36cd461

Please sign in to comment.