aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorST-DDT <[email protected]>2022-12-23 20:42:23 +0100
committerGitHub <[email protected]>2022-12-23 20:42:23 +0100
commit75a31f620c880413c05f012f1924b2ad89fb950c (patch)
tree4f1c7fdb26d22962f98ae191f6364689193d8155
parent4ce8e98fcc19d99bf6df3abb3e24c4667f586076 (diff)
downloadfaker-75a31f620c880413c05f012f1924b2ad89fb950c.tar.xz
faker-75a31f620c880413c05f012f1924b2ad89fb950c.zip
feat(helpers): fake from array (#1453)
-rw-r--r--src/modules/company/index.ts4
-rw-r--r--src/modules/helpers/index.ts130
-rw-r--r--src/modules/location/index.ts10
-rw-r--r--test/__snapshots__/helpers.spec.ts.snap24
-rw-r--r--test/helpers.spec.ts42
5 files changed, 171 insertions, 39 deletions
diff --git a/src/modules/company/index.ts b/src/modules/company/index.ts
index e9e9bf09..d4b181f6 100644
--- a/src/modules/company/index.ts
+++ b/src/modules/company/index.ts
@@ -36,11 +36,9 @@ export class CompanyModule {
* @since 7.4.0
*/
name(): string {
- const pattern = this.faker.helpers.arrayElement(
+ return this.faker.helpers.fake(
this.faker.definitions.company.name_patterns
);
-
- return this.faker.helpers.fake(pattern);
}
/**
diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts
index 4cf9ad38..cb4f7680 100644
--- a/src/modules/helpers/index.ts
+++ b/src/modules/helpers/index.ts
@@ -506,7 +506,7 @@ export class HelpersModule {
* It checks the given string for placeholders and replaces them by calling faker methods:
*
* ```js
- * const hello = faker.helpers.fake('Hi, my name is {{person.firstName}} {{person.lastName}}!')
+ * const hello = faker.helpers.fake('Hi, my name is {{person.firstName}} {{person.lastName}}!');
* ```
*
* This would use the `faker.person.firstName()` and `faker.person.lastName()` method to resolve the placeholders respectively.
@@ -515,18 +515,18 @@ export class HelpersModule {
* and if that isn't possible, we will fall back to string:
*
* ```js
- * const message = faker.helpers.fake('You can call me at {{phone.number(+!# !## #### #####!)}}.')
+ * const message = faker.helpers.fake('You can call me at {{phone.number(+!# !## #### #####!)}}.');
* ```
*
* It is also possible to use multiple parameters (comma separated).
*
* ```js
- * const message = faker.helpers.fake('Your pin is {{string.numeric(4, {"allowLeadingZeros": true})}}.')
+ * const message = faker.helpers.fake('Your pin is {{string.numeric(4, {"allowLeadingZeros": true})}}.');
* ```
*
- * It is also NOT possible to use any non-faker methods or plain javascript in such templates.
+ * It is also NOT possible to use any non-faker methods or plain javascript in such patterns.
*
- * @param str The template string that will get interpolated. Must not be empty.
+ * @param pattern The pattern string that will get interpolated. Must not be empty.
*
* @see faker.helpers.mustache() to use custom functions for resolution.
*
@@ -541,24 +541,127 @@ export class HelpersModule {
*
* @since 7.4.0
*/
- fake(str: string): string {
+ fake(pattern: string): string;
+ /**
+ * Generator for combining faker methods based on an array containing static string inputs.
+ *
+ * Note: We recommend using string template literals instead of `fake()`,
+ * which are faster and strongly typed (if you are using TypeScript),
+ * e.g. ``const address = `${faker.location.zipCode()} ${faker.location.city()}`;``
+ *
+ * This method is useful if you have to build a random string from a static, non-executable source
+ * (e.g. string coming from a user, stored in a database or a file).
+ *
+ * It checks the given string for placeholders and replaces them by calling faker methods:
+ *
+ * ```js
+ * const hello = faker.helpers.fake(['Hi, my name is {{person.firstName}} {{person.lastName}}!']);
+ * ```
+ *
+ * This would use the `faker.person.firstName()` and `faker.person.lastName()` method to resolve the placeholders respectively.
+ *
+ * It is also possible to provide parameters. At first, they will be parsed as json,
+ * and if that isn't possible, it will fall back to string:
+ *
+ * ```js
+ * const message = faker.helpers.fake([
+ * 'You can call me at {{phone.number(+!# !## #### #####!)}}.',
+ * 'My email is {{internet.email}}.',
+ * ]);
+ * ```
+ *
+ * It is also possible to use multiple parameters (comma separated).
+ *
+ * ```js
+ * const message = faker.helpers.fake(['Your pin is {{string.numeric(4, {"allowLeadingZeros": true})}}.']);
+ * ```
+ *
+ * It is also NOT possible to use any non-faker methods or plain javascript in such patterns.
+ *
+ * @param patterns The array to select a pattern from, that will then get interpolated. Must not be empty.
+ *
+ * @see faker.helpers.mustache() to use custom functions for resolution.
+ *
+ * @example
+ * faker.helpers.fake(['A: {{person.firstName}}', 'B: {{person.lastName}}']) // 'A: Barry'
+ *
+ * @since 8.0.0
+ */
+ fake(patterns: string[]): string;
+ /**
+ * Generator for combining faker methods based on a static string input or an array of static string inputs.
+ *
+ * Note: We recommend using string template literals instead of `fake()`,
+ * which are faster and strongly typed (if you are using TypeScript),
+ * e.g. ``const address = `${faker.location.zipCode()} ${faker.location.city()}`;``
+ *
+ * This method is useful if you have to build a random string from a static, non-executable source
+ * (e.g. string coming from a user, stored in a database or a file).
+ *
+ * It checks the given string for placeholders and replaces them by calling faker methods:
+ *
+ * ```js
+ * const hello = faker.helpers.fake('Hi, my name is {{person.firstName}} {{person.lastName}}!');
+ * ```
+ *
+ * This would use the `faker.person.firstName()` and `faker.person.lastName()` method to resolve the placeholders respectively.
+ *
+ * It is also possible to provide parameters. At first, they will be parsed as json,
+ * and if that isn't possible, it will fall back to string:
+ *
+ * ```js
+ * const message = faker.helpers.fake('You can call me at {{phone.number(+!# !## #### #####!)}}.');
+ * ```
+ *
+ * It is also possible to use multiple parameters (comma separated).
+ *
+ * ```js
+ * const message = faker.helpers.fake('Your pin is {{string.numeric(4, {"allowLeadingZeros": true})}}.');
+ * ```
+ *
+ * It is also NOT possible to use any non-faker methods or plain javascript in such patterns.
+ *
+ * @param pattern The pattern string that will get interpolated. Must not be empty. If an array is passed, a random element will be picked and interpolated.
+ *
+ * @see faker.helpers.mustache() to use custom functions for resolution.
+ *
+ * @example
+ * faker.helpers.fake('{{person.lastName}}') // 'Barrows'
+ * faker.helpers.fake('{{person.lastName}}, {{person.firstName}} {{person.suffix}}') // 'Durgan, Noe MD'
+ * faker.helpers.fake('This is static test.') // 'This is static test.'
+ * faker.helpers.fake('Good Morning {{person.firstName}}!') // 'Good Morning Estelle!'
+ * faker.helpers.fake('You can call me at {{phone.number(!## ### #####!)}}.') // 'You can call me at 202 555 973722.'
+ * faker.helpers.fake('I flipped the coin and got: {{helpers.arrayElement(["heads", "tails"])}}') // 'I flipped the coin and got: tails'
+ * faker.helpers.fake(['A: {{person.firstName}}', 'B: {{person.lastName}}']) // 'A: Barry'
+ *
+ * @since 7.4.0
+ */
+ fake(pattern: string | string[]): string;
+ fake(pattern: string | string[]): string {
+ if (Array.isArray(pattern)) {
+ pattern = this.arrayElement(pattern);
+ // TODO @ST-DDT 2022-10-15: Remove this check after we fail in `arrayElement` when the array is empty
+ if (pattern == null) {
+ throw new FakerError('Array of pattern strings cannot be empty.');
+ }
+ }
// if incoming str parameter is not provided, return error message
- if (typeof str !== 'string' || str.length === 0) {
- throw new FakerError('string parameter is required!');
+ if (pattern.length === 0) {
+ throw new FakerError('Pattern string cannot be empty.');
}
// find first matching {{ and }}
- const start = str.search(/{{[a-z]/);
- const end = str.indexOf('}}', start);
+ const start = pattern.search(/{{[a-z]/);
+ const end = pattern.indexOf('}}', start);
// if no {{ and }} is found, we are done
if (start === -1 || end === -1) {
- return str;
+ return pattern;
}
// extract method name from between the {{ }} that we found
// for example: {{person.firstName}}
- const token = str.substring(start + 2, end + 2);
+ const token = pattern.substring(start + 2, end + 2);
let method = token.replace('}}', '').replace('{{', '');
// extract method parameters
@@ -615,7 +718,8 @@ export class HelpersModule {
// Replace the found tag with the returned fake value
// We cannot use string.replace here because the result might contain evaluated characters
- const res = str.substring(0, start) + result + str.substring(end + 2);
+ const res =
+ pattern.substring(0, start) + result + pattern.substring(end + 2);
if (res === '') {
return '';
diff --git a/src/modules/location/index.ts b/src/modules/location/index.ts
index a4238241..a53c11d7 100644
--- a/src/modules/location/index.ts
+++ b/src/modules/location/index.ts
@@ -75,10 +75,7 @@ export class LocationModule {
* @since 8.0.0
*/
city(): string {
- const pattern = this.faker.helpers.arrayElement(
- this.faker.definitions.location.city
- );
- return this.faker.helpers.fake(pattern);
+ return this.faker.helpers.fake(this.faker.definitions.location.city);
}
/**
@@ -121,10 +118,7 @@ export class LocationModule {
* @since 8.0.0
*/
street(): string {
- const format = this.faker.helpers.arrayElement(
- this.faker.definitions.location.street
- );
- return this.faker.helpers.fake(format);
+ return this.faker.helpers.fake(this.faker.definitions.location.street);
}
/**
diff --git a/test/__snapshots__/helpers.spec.ts.snap b/test/__snapshots__/helpers.spec.ts.snap
index 06e0bc43..4ce31832 100644
--- a/test/__snapshots__/helpers.spec.ts.snap
+++ b/test/__snapshots__/helpers.spec.ts.snap
@@ -29,9 +29,13 @@ exports[`helpers > 42 > arrayElements > with array and count 1`] = `
]
`;
-exports[`helpers > 42 > fake > with args 1`] = `"my string: Cky2eiXX/J"`;
+exports[`helpers > 42 > fake > with a dynamic template 1`] = `"my string: Cky2eiXX/J"`;
-exports[`helpers > 42 > fake > with plain string 1`] = `"my test string"`;
+exports[`helpers > 42 > fake > with a static template 1`] = `"my test string"`;
+
+exports[`helpers > 42 > fake > with multiple dynamic templates 1`] = `"Sandy"`;
+
+exports[`helpers > 42 > fake > with multiple static templates 1`] = `"B"`;
exports[`helpers > 42 > maybe > with only value 1`] = `"Hello World!"`;
@@ -208,9 +212,13 @@ exports[`helpers > 1211 > arrayElements > with array and count 1`] = `
]
`;
-exports[`helpers > 1211 > fake > with args 1`] = `"my string: wKti5-}$_/"`;
+exports[`helpers > 1211 > fake > with a dynamic template 1`] = `"my string: wKti5-}$_/"`;
+
+exports[`helpers > 1211 > fake > with a static template 1`] = `"my test string"`;
-exports[`helpers > 1211 > fake > with plain string 1`] = `"my test string"`;
+exports[`helpers > 1211 > fake > with multiple dynamic templates 1`] = `"La Crosse"`;
+
+exports[`helpers > 1211 > fake > with multiple static templates 1`] = `"C"`;
exports[`helpers > 1211 > maybe > with only value 1`] = `undefined`;
@@ -383,9 +391,13 @@ exports[`helpers > 1337 > arrayElements > with array and count 1`] = `
]
`;
-exports[`helpers > 1337 > fake > with args 1`] = `"my string: 9U/4:SK$>6"`;
+exports[`helpers > 1337 > fake > with a dynamic template 1`] = `"my string: 9U/4:SK$>6"`;
+
+exports[`helpers > 1337 > fake > with a static template 1`] = `"my test string"`;
+
+exports[`helpers > 1337 > fake > with multiple dynamic templates 1`] = `"U/4:SK$>6Q"`;
-exports[`helpers > 1337 > fake > with plain string 1`] = `"my test string"`;
+exports[`helpers > 1337 > fake > with multiple static templates 1`] = `"A"`;
exports[`helpers > 1337 > maybe > with only value 1`] = `"Hello World!"`;
diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts
index 5829ddd8..37a1bd02 100644
--- a/test/helpers.spec.ts
+++ b/test/helpers.spec.ts
@@ -96,10 +96,14 @@ describe('helpers', () => {
});
t.describe('fake', (t) => {
- t.it('with plain string', 'my test string').it(
- 'with args',
- 'my string: {{datatype.string}}'
- );
+ t.it('with a static template', 'my test string')
+ .it('with a dynamic template', 'my string: {{string.sample}}')
+ .it('with multiple static templates', ['A', 'B', 'C'])
+ .it('with multiple dynamic templates', [
+ '{{string.sample}}',
+ '{{location.city_name}}',
+ '{{location.cityName}}',
+ ]);
});
t.describe('rangeToNumber', (t) => {
@@ -598,11 +602,16 @@ describe('helpers', () => {
expect(actual).toMatch(/^\d{5}$/);
});
- it('does not allow undefined parameters', () => {
- expect(() =>
- // @ts-expect-error: The parameter is required
- faker.helpers.fake()
- ).toThrowError(new FakerError('string parameter is required!'));
+ it('does not allow empty string parameters', () => {
+ expect(() => faker.helpers.fake('')).toThrowError(
+ new FakerError('Pattern string cannot be empty.')
+ );
+ });
+
+ it('does not allow empty array parameters', () => {
+ expect(() => faker.helpers.fake([])).toThrowError(
+ new FakerError('Array of pattern strings cannot be empty.')
+ );
});
it('does not allow invalid module name', () => {
@@ -655,6 +664,21 @@ describe('helpers', () => {
);
});
+ it('should be able to pass multiple static templates', () => {
+ expect(['A', 'B', 'C']).toContain(
+ faker.helpers.fake(['A', 'B', 'C'])
+ );
+ });
+
+ it('should be able to pass multiple dynamic templates', () => {
+ expect(faker.definitions.location.city_name).toContain(
+ faker.helpers.fake([
+ '{{location.city_name}}',
+ '{{location.cityName}}',
+ ])
+ );
+ });
+
it('should be able to handle only {{ brackets', () => {
expect(faker.helpers.fake('{{hello')).toBe('{{hello');
expect(faker.helpers.fake('hello{{')).toBe('hello{{');