Skip to content

Commit

Permalink
feat: fake with multiple parameters (#1459)
Browse files Browse the repository at this point in the history
  • Loading branch information
ST-DDT committed Oct 23, 2022
1 parent f4907a1 commit 2eb2537
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 27 deletions.
26 changes: 13 additions & 13 deletions src/modules/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -487,10 +487,14 @@ 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(+!# !## #### #####!)}}.')
* ```
*
* Currently it is not possible to set more than a single parameter.
* 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 templates.
*
Expand All @@ -505,6 +509,7 @@ export class HelpersModule {
* 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('I rolled the dice and got: {{string.numeric(1, {"allowLeadingZeros": true})}}') // 'I rolled the dice and got: 6'
*
* @since 7.4.0
*/
Expand All @@ -529,7 +534,7 @@ export class HelpersModule {
let method = token.replace('}}', '').replace('{{', '');

// extract method parameters
const regExp = /\(([^)]+)\)/;
const regExp = /\(([^)]*)\)/;
const matches = regExp.exec(method);
let parameters = '';
if (matches) {
Expand All @@ -550,7 +555,7 @@ export class HelpersModule {
}

// Make method executable
let fn: (args?: unknown) => unknown;
let fn: (...args: unknown[]) => unknown;
if (typeof currentModuleOrMethod === 'function') {
fn = currentModuleOrMethod as (args?: unknown) => unknown;
} else if (Array.isArray(currentDefinitions)) {
Expand All @@ -568,22 +573,17 @@ export class HelpersModule {
// If parameters are populated here, they are always going to be of string type
// since we might actually be dealing with an object or array,
// we always attempt to the parse the incoming parameters into JSON
let params: unknown;
let params: unknown[];
// Note: we experience a small performance hit here due to JSON.parse try / catch
// If anyone actually needs to optimize this specific code path, please open a support issue on github
try {
params = JSON.parse(parameters);
params = JSON.parse(`[${parameters}]`);
} catch (err) {
// since JSON.parse threw an error, assume parameters was actually a string
params = parameters;
params = [parameters];
}

let result: string;
if (typeof params === 'string' && params.length === 0) {
result = String(fn());
} else {
result = String(fn(params));
}
const result = String(fn(...params));

// Replace the found tag with the returned fake value
// We cannot use string.replace here because the result might contain evaluated characters
Expand Down
48 changes: 34 additions & 14 deletions test/helpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,31 +488,51 @@ describe('helpers', () => {
});

describe('fake()', () => {
it('replaces a token with a random value for a method with no parameters', () => {
const name = faker.helpers.fake('{{phone.number}}');
expect(name).toMatch(/\d/);
it('replaces a token with a random value for a method without parentheses', () => {
const actual = faker.helpers.fake('{{string.numeric}}');
expect(actual).toMatch(/^\d$/);
});

it('replaces multiple tokens with random values for methods with no parameters', () => {
const name = faker.helpers.fake(
'{{helpers.arrayElement}}{{helpers.arrayElement}}{{helpers.arrayElement}}'
it('replaces multiple tokens with random values for methods without parentheses', () => {
const actual = faker.helpers.fake(
'{{string.numeric}}{{string.numeric}}{{string.numeric}}'
);
expect(name).toMatch(/[abc]{3}/);
expect(actual).toMatch(/^\d{3}$/);
});

it('replaces a token with a random value for a methods with a simple parameter', () => {
const random = faker.helpers.fake(
'{{helpers.slugify("Will This Work")}}'
);
expect(random).toBe('Will-This-Work');
it('replaces a token with a random value for a method with empty parentheses', () => {
const actual = faker.helpers.fake('{{string.numeric()}}');
expect(actual).toMatch(/^\d$/);
});

it('replaces a token with a random value for a method with an unquoted parameter', () => {
const random = faker.helpers.fake('{{helpers.slugify(This Works)}}');
expect(random).toBe('This-Works');
});

it('replaces a token with a random value for a method with a simple parameter', () => {
const actual = faker.helpers.fake('{{string.numeric(3)}}');
expect(actual).toMatch(/^\d{3}$/);
});

it('replaces a token with a random value for a method with an array parameter', () => {
const arr = ['one', 'two', 'three'];
const random = faker.helpers.fake(
const actual = faker.helpers.fake(
'{{helpers.arrayElement(["one", "two", "three"])}}'
);
expect(arr).toContain(random);
expect(arr).toContain(actual);
});

it('replaces a token with a random value for a method with an object parameter', () => {
const actual = faker.helpers.fake('{{random.alpha({"count": 3})}}');
expect(actual).toMatch(/^[a-z]{3}$/i);
});

it('replaces a token with a random value for a method with multiple parameters', () => {
const actual = faker.helpers.fake(
'{{string.numeric(5, {"allowLeadingZeros": true})}}'
);
expect(actual).toMatch(/^\d{5}$/);
});

it('does not allow undefined parameters', () => {
Expand Down

0 comments on commit 2eb2537

Please sign in to comment.