Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(string): generate string from characters #1717

Merged
merged 11 commits into from
Jan 11, 2023
135 changes: 65 additions & 70 deletions src/modules/string/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,49 @@ export class StringModule {
}
}

/**
* Generates a string from the given characters.
*
* @param characters The characters to use for the string. Can be a string or an array of characters.
* If it is an array, then each element is treated as a single character even if it is a string with multiple characters.
* @param length The length of the string to generate. Defaults to `1`.
* @param length.min The minimum length of the string to generate.
* @param length.max The maximum length of the string to generate.
*
* @example
* faker.string.fromCharacters('abc') // 'c'
* faker.string.fromCharacters(['a', 'b', 'c']) // 'a'
* faker.string.fromCharacters('abc', 10) // 'cbbbacbacb'
* faker.string.fromCharacters('abc', { min: 5, max: 10 }) // 'abcaaaba'
*
* @since 8.0.0
*/
fromCharacters(
characters: string | ReadonlyArray<string>,
length: number | { min: number; max: number } = 1
): string {
length = this.faker.helpers.rangeToNumber(length);
if (length <= 0) {
return '';
}

if (typeof characters === 'string') {
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
characters = characters.split('');
}

if (characters.length === 0) {
throw new FakerError(
'Unable to generate string: No characters to select from.'
);
}

return this.faker.helpers
.multiple(() => this.faker.helpers.arrayElement(characters as string[]), {
count: length,
})
.join('');
}

/**
* Generating a string consisting of letters in the English alphabet.
*
Expand Down Expand Up @@ -157,15 +200,7 @@ export class StringModule {

charsArray = charsArray.filter((elem) => !exclude.includes(elem));

if (charsArray.length === 0) {
throw new FakerError(
'Unable to generate string, because all possible characters are excluded.'
);
}

return Array.from({ length }, () =>
this.faker.helpers.arrayElement(charsArray)
).join('');
return this.fromCharacters(charsArray, length);
}

/**
Expand Down Expand Up @@ -230,15 +265,7 @@ export class StringModule {

charsArray = charsArray.filter((elem) => !exclude.includes(elem));

if (charsArray.length === 0) {
throw new FakerError(
'Unable to generate string, because all possible characters are excluded.'
);
}

return Array.from({ length }, () =>
this.faker.helpers.arrayElement(charsArray)
).join('');
return this.fromCharacters(charsArray, length);
}

/**
Expand Down Expand Up @@ -266,18 +293,10 @@ export class StringModule {
} = {}
): string {
const { prefix = '0b' } = options;
const length = this.faker.helpers.rangeToNumber(options.length ?? 1);
if (length <= 0) {
return prefix;
}

let binaryString = '';

for (let i = 0; i < length; i++) {
binaryString += this.faker.helpers.arrayElement(['0', '1']);
}

return `${prefix}${binaryString}`;
let result = prefix;
result += this.fromCharacters(['0', '1'], options.length ?? 1);
return result;
}

/**
Expand Down Expand Up @@ -305,27 +324,13 @@ export class StringModule {
} = {}
): string {
const { prefix = '0o' } = options;
const length = this.faker.helpers.rangeToNumber(options.length ?? 1);
if (length <= 0) {
return prefix;
}

let octalString = '';

for (let i = 0; i < length; i++) {
octalString += this.faker.helpers.arrayElement([
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
]);
}

return `${prefix}${octalString}`;
let result = prefix;
result += this.fromCharacters(
['0', '1', '2', '3', '4', '5', '6', '7'],
options.length ?? 1
);
return result;
}

/**
Expand Down Expand Up @@ -362,10 +367,8 @@ export class StringModule {
return prefix;
}

let wholeString = '';

for (let i = 0; i < length; i++) {
wholeString += this.faker.helpers.arrayElement([
let wholeString = this.fromCharacters(
[
'0',
'1',
'2',
Expand All @@ -388,8 +391,9 @@ export class StringModule {
'D',
'E',
'F',
]);
}
],
length
);

if (casing === 'upper') {
wholeString = wholeString.toUpperCase();
Expand Down Expand Up @@ -470,9 +474,7 @@ export class StringModule {
);
}

while (result.length < length) {
result += this.faker.helpers.arrayElement(allowedDigits);
}
result += this.fromCharacters(allowedDigits, length - result.length);

return result;
}
Expand Down Expand Up @@ -589,14 +591,8 @@ export class StringModule {
* @since 8.0.0
*/
special(length: number | { min: number; max: number } = 1): string {
length = this.faker.helpers.rangeToNumber(length);
if (length <= 0) {
return '';
}

let specialString = '';
for (let i = 0; i < length; i++) {
specialString += this.faker.helpers.arrayElement([
return this.fromCharacters(
[
'!',
'"',
'#',
Expand Down Expand Up @@ -629,9 +625,8 @@ export class StringModule {
'|',
'}',
'~',
]);
}

return specialString;
],
length
);
}
}
36 changes: 36 additions & 0 deletions test/__snapshots__/string.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ exports[`string > 42 > binary > with length and empty prefix 1`] = `"0110111"`;

exports[`string > 42 > binary > with length range 1`] = `"0b11011110000001"`;

exports[`string > 42 > fromCharacters > with string characters 1`] = `"o"`;

exports[`string > 42 > fromCharacters > with string characters and length 1`] = `"oaroa"`;

exports[`string > 42 > fromCharacters > with string characters and length range 1`] = `"aroaabbfofffor"`;

exports[`string > 42 > fromCharacters > with string[] characters 1`] = `"o"`;

exports[`string > 42 > fromCharacters > with string[] characters and length 1`] = `"oaroa"`;

exports[`string > 42 > fromCharacters > with string[] characters and length range 1`] = `"aroaabbfofffor"`;

exports[`string > 42 > hexadecimal > noArgs 1`] = `"0x8"`;

exports[`string > 42 > hexadecimal > with casing = lower 1`] = `"0x8"`;
Expand Down Expand Up @@ -224,6 +236,18 @@ exports[`string > 1211 > binary > with length and empty prefix 1`] = `"1011001"`

exports[`string > 1211 > binary > with length range 1`] = `"0b01100101010100011101"`;

exports[`string > 1211 > fromCharacters > with string characters 1`] = `"r"`;

exports[`string > 1211 > fromCharacters > with string characters and length 1`] = `"rorao"`;

exports[`string > 1211 > fromCharacters > with string characters and length range 1`] = `"oraofrfafaoaoofaaafa"`;

exports[`string > 1211 > fromCharacters > with string[] characters 1`] = `"r"`;

exports[`string > 1211 > fromCharacters > with string[] characters and length 1`] = `"rorao"`;

exports[`string > 1211 > fromCharacters > with string[] characters and length range 1`] = `"oraofrfafaoaoofaaafa"`;

exports[`string > 1211 > hexadecimal > noArgs 1`] = `"0xE"`;

exports[`string > 1211 > hexadecimal > with casing = lower 1`] = `"0xe"`;
Expand Down Expand Up @@ -386,6 +410,18 @@ exports[`string > 1337 > binary > with length and empty prefix 1`] = `"0100010"`

exports[`string > 1337 > binary > with length range 1`] = `"0b100010000110"`;

exports[`string > 1337 > fromCharacters > with string characters 1`] = `"o"`;

exports[`string > 1337 > fromCharacters > with string characters and length 1`] = `"obfoo"`;

exports[`string > 1337 > fromCharacters > with string characters and length range 1`] = `"bfoobofoobbo"`;

exports[`string > 1337 > fromCharacters > with string[] characters 1`] = `"o"`;

exports[`string > 1337 > fromCharacters > with string[] characters and length 1`] = `"obfoo"`;

exports[`string > 1337 > fromCharacters > with string[] characters and length range 1`] = `"bfoobofoobbo"`;

exports[`string > 1337 > hexadecimal > noArgs 1`] = `"0x5"`;

exports[`string > 1337 > hexadecimal > with casing = lower 1`] = `"0x5"`;
Expand Down
3 changes: 3 additions & 0 deletions test/all_functional.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const BROKEN_LOCALE_METHODS = {
state: ['az', 'cz', 'nb_NO', 'sk'],
stateAbbr: ['cz', 'sk'],
},
string: {
fromCharacters: '*',
},
person: {
prefix: ['az', 'id_ID', 'ru', 'zh_CN', 'zh_TW'],
suffix: ['az', 'it', 'mk', 'pt_PT', 'ru'],
Expand Down
4 changes: 2 additions & 2 deletions test/random.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ describe('random', () => {
})
).toThrowError(
new FakerError(
'Unable to generate string, because all possible characters are excluded.'
'Unable to generate string: No characters to select from.'
)
);
});
Expand Down Expand Up @@ -332,7 +332,7 @@ describe('random', () => {
})
).toThrowError(
new FakerError(
'Unable to generate string, because all possible characters are excluded.'
'Unable to generate string: No characters to select from.'
)
);
});
Expand Down
Loading