From 80e0a9688099677a74614ccbedc9231b6382c4eb Mon Sep 17 00:00:00 2001 From: Pablo Ladreyt Date: Thu, 5 Jan 2023 15:43:43 -0300 Subject: [PATCH] feat(string): add binary and octal random string generation (#1710) --- src/modules/number/index.ts | 4 + src/modules/string/index.ts | 87 +++++++++++++++++++++ test/__snapshots__/string.spec.ts.snap | 60 +++++++++++++++ test/string.spec.ts | 100 +++++++++++++++++++++++++ 4 files changed, 251 insertions(+) diff --git a/src/modules/number/index.ts b/src/modules/number/index.ts index 6a5fd5d6f77..5a2f0cb6411 100644 --- a/src/modules/number/index.ts +++ b/src/modules/number/index.ts @@ -123,6 +123,8 @@ export class NumberModule { * * @throws When options define `max < min`. * + * @see faker.string.binary() If you would like to generate a `binary string` with a given length (range). + * * @example * faker.number.binary() // '1' * faker.number.binary(255) // '110101' @@ -152,6 +154,8 @@ export class NumberModule { * * @throws When options define `max < min`. * + * @see faker.string.octal() If you would like to generate an `octal string` with a given length (range). + * * @example * faker.number.octal() // '5' * faker.number.octal(255) // '377' diff --git a/src/modules/string/index.ts b/src/modules/string/index.ts index ab16dc34bf8..85d29b9dcc2 100644 --- a/src/modules/string/index.ts +++ b/src/modules/string/index.ts @@ -241,6 +241,93 @@ export class StringModule { ).join(''); } + /** + * Returns a [binary](https://en.wikipedia.org/wiki/Binary_number) string. + * + * @param options The optional options object. + * @param options.length The number or range of characters to generate after the prefix. Defaults to `1`. + * @param options.prefix Prefix for the generated number. Defaults to `'0b'`. + * + * @see faker.number.binary() If you would like to generate a `binary number` (within a range). + * + * @example + * faker.string.binary() // '0b1' + * faker.string.binary({ length: 10 }) // '0b1101011011' + * faker.string.binary({ length: { min: 5, max: 10 } }) // '0b11101011' + * faker.string.binary({ prefix: '0b' }) // '0b1' + * faker.string.binary({ length: 10, prefix: 'bin_' }) // 'bin_1101011011' + * + * @since 8.0.0 + */ + binary( + options: { + length?: number | { min: number; max: number }; + prefix?: string; + } = {} + ): 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}`; + } + + /** + * Returns an [octal](https://en.wikipedia.org/wiki/Octal) string. + * + * @param options The optional options object. + * @param options.length The number or range of characters to generate after the prefix. Defaults to `1`. + * @param options.prefix Prefix for the generated number. Defaults to `'0o'`. + * + * @see faker.number.octal() If you would like to generate an `octal number` (within a range). + * + * @example + * faker.string.octal() // '0o3' + * faker.string.octal({ length: 10 }) // '0o1526216210' + * faker.string.octal({ length: { min: 5, max: 10 } }) // '0o15263214' + * faker.string.octal({ prefix: '0o' }) // '0o7' + * faker.string.octal({ length: 10, prefix: 'oct_' }) // 'oct_1542153414' + * + * @since 8.0.0 + */ + octal( + options: { + length?: number | { min: number; max: number }; + prefix?: string; + } = {} + ): 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}`; + } + /** * Returns a [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) string. * diff --git a/test/__snapshots__/string.spec.ts.snap b/test/__snapshots__/string.spec.ts.snap index bd7522f92a8..0a6df4d9abc 100644 --- a/test/__snapshots__/string.spec.ts.snap +++ b/test/__snapshots__/string.spec.ts.snap @@ -52,6 +52,16 @@ exports[`string > 42 > alphanumeric > with length range 1`] = `"NWbJMBB9r963sR"` exports[`string > 42 > alphanumeric > with length, casing and exclude 1`] = `"cvy4kvh"`; +exports[`string > 42 > binary > noArgs 1`] = `"0b0"`; + +exports[`string > 42 > binary > with custom prefix 1`] = `"bin_0"`; + +exports[`string > 42 > binary > with length 1`] = `"0b011011"`; + +exports[`string > 42 > binary > with length and empty prefix 1`] = `"0110111"`; + +exports[`string > 42 > binary > with length range 1`] = `"0b11011110000001"`; + exports[`string > 42 > hexadecimal > noArgs 1`] = `"0x8"`; exports[`string > 42 > hexadecimal > with casing = lower 1`] = `"0x8"`; @@ -90,6 +100,16 @@ exports[`string > 42 > numeric > with length range 1`] = `"79177551410048"`; exports[`string > 42 > numeric > with length, allowLeadingZeros and exclude 1`] = `"6890887"`; +exports[`string > 42 > octal > noArgs 1`] = `"0o2"`; + +exports[`string > 42 > octal > with custom prefix 1`] = `"oct_2"`; + +exports[`string > 42 > octal > with length 1`] = `"0o267156"`; + +exports[`string > 42 > octal > with length and empty prefix 1`] = `"2671564"`; + +exports[`string > 42 > octal > with length range 1`] = `"0o67156441310036"`; + exports[`string > 42 > sample > noArgs 1`] = `"Cky2eiXX/J"`; exports[`string > 42 > sample > with length parameter 1`] = `"Cky2e"`; @@ -180,6 +200,16 @@ exports[`string > 1211 > alphanumeric > with length range 1`] = `"sTMd8Z2F9GdLql exports[`string > 1211 > alphanumeric > with length, casing and exclude 1`] = `"yexv53z"`; +exports[`string > 1211 > binary > noArgs 1`] = `"0b1"`; + +exports[`string > 1211 > binary > with custom prefix 1`] = `"bin_1"`; + +exports[`string > 1211 > binary > with length 1`] = `"0b101100"`; + +exports[`string > 1211 > binary > with length and empty prefix 1`] = `"1011001"`; + +exports[`string > 1211 > binary > with length range 1`] = `"0b01100101010100011101"`; + exports[`string > 1211 > hexadecimal > noArgs 1`] = `"0xE"`; exports[`string > 1211 > hexadecimal > with casing = lower 1`] = `"0xe"`; @@ -218,6 +248,16 @@ exports[`string > 1211 > numeric > with length range 1`] = `"4872190616274316780 exports[`string > 1211 > numeric > with length, allowLeadingZeros and exclude 1`] = `"9798609"`; +exports[`string > 1211 > octal > noArgs 1`] = `"0o7"`; + +exports[`string > 1211 > octal > with custom prefix 1`] = `"oct_7"`; + +exports[`string > 1211 > octal > with length 1`] = `"0o737611"`; + +exports[`string > 1211 > octal > with length and empty prefix 1`] = `"7376117"`; + +exports[`string > 1211 > octal > with length range 1`] = `"0o37611705151632155606"`; + exports[`string > 1211 > sample > noArgs 1`] = `"wKti5-}$_/"`; exports[`string > 1211 > sample > with length parameter 1`] = `"wKti5"`; @@ -308,6 +348,16 @@ exports[`string > 1337 > alphanumeric > with length range 1`] = `"y9dhxs2jewAg"` exports[`string > 1337 > alphanumeric > with length, casing and exclude 1`] = `"ag45age"`; +exports[`string > 1337 > binary > noArgs 1`] = `"0b0"`; + +exports[`string > 1337 > binary > with custom prefix 1`] = `"bin_0"`; + +exports[`string > 1337 > binary > with length 1`] = `"0b010001"`; + +exports[`string > 1337 > binary > with length and empty prefix 1`] = `"0100010"`; + +exports[`string > 1337 > binary > with length range 1`] = `"0b100010000110"`; + exports[`string > 1337 > hexadecimal > noArgs 1`] = `"0x5"`; exports[`string > 1337 > hexadecimal > with casing = lower 1`] = `"0x5"`; @@ -346,6 +396,16 @@ exports[`string > 1337 > numeric > with length range 1`] = `"512254032552"`; exports[`string > 1337 > numeric > with length, allowLeadingZeros and exclude 1`] = `"6706677"`; +exports[`string > 1337 > octal > noArgs 1`] = `"0o2"`; + +exports[`string > 1337 > octal > with custom prefix 1`] = `"oct_2"`; + +exports[`string > 1337 > octal > with length 1`] = `"0o241124"`; + +exports[`string > 1337 > octal > with length and empty prefix 1`] = `"2411243"`; + +exports[`string > 1337 > octal > with length range 1`] = `"0o411243021442"`; + exports[`string > 1337 > sample > noArgs 1`] = `"9U/4:SK$>6"`; exports[`string > 1337 > sample > with length parameter 1`] = `"9U/4:"`; diff --git a/test/string.spec.ts b/test/string.spec.ts index 8963e3cf095..c9f82593904 100644 --- a/test/string.spec.ts +++ b/test/string.spec.ts @@ -39,6 +39,28 @@ describe('string', () => { }); }); + t.describe('binary', (t) => { + t.it('noArgs') + .it('with length', { length: 6 }) + .it('with length range', { length: { min: 10, max: 20 } }) + .it('with custom prefix', { prefix: 'bin_' }) + .it('with length and empty prefix', { + length: 7, + prefix: '', + }); + }); + + t.describe('octal', (t) => { + t.it('noArgs') + .it('with length', { length: 6 }) + .it('with length range', { length: { min: 10, max: 20 } }) + .it('with custom prefix', { prefix: 'oct_' }) + .it('with length and empty prefix', { + length: 7, + prefix: '', + }); + }); + t.describe('hexadecimal', (t) => { t.it('noArgs') .it('with length', { length: 6 }) @@ -344,6 +366,84 @@ describe('string', () => { }); }); + describe(`binary`, () => { + it('generates a single binary character when no additional argument was provided', () => { + const binary = faker.string.binary(); + expect(binary).toMatch(/^0b[01]$/i); + expect(binary).toHaveLength(3); + }); + + it('generates a random binary string with fixed length and no prefix', () => { + const binary = faker.string.binary({ + length: 5, + prefix: '', + }); + expect(binary).toMatch(/^[01]*$/i); + expect(binary).toHaveLength(5); + }); + + it.each([0, -1, -100])( + 'should return the prefix when length is <= 0', + (length) => { + const binary = faker.string.binary({ length }); + + expect(binary).toBe('0b'); + } + ); + + it('should return a binary string with a random amount of characters and no prefix', () => { + const binary = faker.string.binary({ + length: { min: 10, max: 20 }, + prefix: '', + }); + + expect(binary).toBeDefined(); + expect(binary).toBeTypeOf('string'); + + expect(binary.length).toBeGreaterThanOrEqual(10); + expect(binary.length).toBeLessThanOrEqual(20); + }); + }); + + describe(`octal`, () => { + it('generates single octal character when no additional argument was provided', () => { + const octal = faker.string.octal(); + expect(octal).toMatch(/^0o[0-7]$/i); + expect(octal).toHaveLength(3); + }); + + it('generates a random octal string with fixed length and no prefix', () => { + const octal = faker.string.octal({ + length: 5, + prefix: '', + }); + expect(octal).toMatch(/^[0-7]*$/i); + expect(octal).toHaveLength(5); + }); + + it.each([0, -1, -100])( + 'should return the prefix when length is <= 0', + (length) => { + const octal = faker.string.octal({ length }); + + expect(octal).toBe('0o'); + } + ); + + it('should return an octal string with a random amount of characters and no prefix', () => { + const octal = faker.string.octal({ + length: { min: 10, max: 20 }, + prefix: '', + }); + + expect(octal).toBeDefined(); + expect(octal).toBeTypeOf('string'); + + expect(octal.length).toBeGreaterThanOrEqual(10); + expect(octal.length).toBeLessThanOrEqual(20); + }); + }); + describe(`hexadecimal`, () => { it('generates single hex character when no additional argument was provided', () => { const hex = faker.string.hexadecimal();