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

[1673] Ensure mix_case returns at least one lower and one upper case … #1694

Merged
merged 1 commit into from
Aug 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[1673] Ensure mix_case returns at least one lower and one upper case …
…letter
  • Loading branch information
brad authored and bpleslie committed Aug 26, 2019
commit 942091a6b189297895d1a008b19fa65cf1f5000c
4 changes: 3 additions & 1 deletion doc/default/alphanumeric.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# Keyword arguments: number
Faker::Alphanumeric.alpha(number: 10) #=> "zlvubkrwga"

# Keyword arguments: number
# Keyword arguments: number, min_alpha, min_numeric
Faker::Alphanumeric.alphanumeric(number: 10) #=> "3yfq2phxtb"
Faker::Alphanumeric.alphanumeric(number: 10, min_alpha: 3) #=> "3yfq2phxtb"
Faker::Alphanumeric.alphanumeric(number: 10, min_alpha: 3, min_numeric: 3) #=> "3yfq2phx8b"
```
4 changes: 3 additions & 1 deletion doc/default/lorem.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ Faker::Lorem.words(number: 4, supplemental: true) #=> ["colloco", "qui", "vergo"

Faker::Lorem.multibyte #=> 😀

# Keyword arguments: number
# Keyword arguments: number, min_alpha, min_numeric
Faker::Lorem.characters #=> "uw1ep04lhs0c4d931n1jmrspprf5wrj85fefue0y7y6m56b6omquh7br7dhqijwlawejpl765nb1716idmp3xnfo85v349pzy2o9rir23y2qhflwr71c1585fnynguiphkjm8p0vktwitcsm16lny7jzp9t4drwav3qmhz4yjq4k04x14gl6p148hulyqioo72tf8nwrxxcclfypz2lc58lsibgfe5w5p0xv95peafjjmm2frkhdc6duoky0aha"
Faker::Lorem.characters(number: 10) #=> "ang9cbhoa8"
Faker::Lorem.characters(number: 10, min_alpha: 4) #=> "ang9cbhoa8"
Faker::Lorem.characters(number: 10, min_alpha: 4, min_numeric: 1) #=> "ang9cbhoa8"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks 👍


# Keyword arguments: word_count, supplemental, random_words_to_add
# The 'random_words_to_add' argument increases the sentence's word count by a random value within (0..random_words_to_add).
Expand Down
3 changes: 2 additions & 1 deletion lib/faker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ def random
class Base
Numbers = Array(0..9)
ULetters = Array('A'..'Z')
Letters = ULetters + Array('a'..'z')
LLetters = Array('a'..'z')
Letters = ULetters + LLetters

class << self
NOT_GIVEN = Object.new
Expand Down
44 changes: 36 additions & 8 deletions lib/faker/default/alphanumeric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,60 @@

module Faker
class Alphanumeric < Base
class << self
ALPHABET = ('a'..'z').to_a
ALPHANUMS = ALPHABET + (0..9).to_a
ALPHANUMS = LLetters + Numbers

class << self
def alpha(legacy_number = NOT_GIVEN, number: 32)
if legacy_number != NOT_GIVEN
warn_with_uplevel 'Passing `number` with the 1st argument of `Alphanumeric.alpha` is deprecated. Use keyword argument like `Alphanumeric.alpha(number: ...)` instead.', uplevel: 1
number = legacy_number
end

char_count = resolve(number)
return '' if char_count.to_i < 1

Array.new(char_count) { sample(ALPHABET) }.join
Array.new(char_count) { sample(self::LLetters) }.join
end

def alphanumeric(legacy_number = NOT_GIVEN, number: 32)
##
# Produces a random string of alphanumeric characters
#
# @param [Integer] number
# @param [Integer] min_alpha
# @param [Integer] min_numeric
#
# @return [String]
#
# @example Faker::Alphanumeric.alphanumeric(number: 10) #=> "3yfq2phxtb"
# @example Faker::Alphanumeric.alphanumeric(number: 10, min_alpha: 3) #=> "3yfq2phxtb"
# @example Faker::Alphanumeric.alphanumeric(number: 10, min_alpha: 3, min_numeric: 3) #=> "3yfq2phx8b"
#
# @faker.version 2.1.3
def alphanumeric(legacy_number = NOT_GIVEN, number: 32, min_alpha: 0, min_numeric: 0)
if legacy_number != NOT_GIVEN
warn_with_uplevel 'Passing `number` with the 1st argument of `Alphanumeric.alphanumeric` is deprecated. Use keyword argument like `Alphanumeric.alphanumeric(number: ...)` instead.', uplevel: 1
number = legacy_number
end

char_count = resolve(number)
return '' if char_count.to_i < 1
raise ArgumentError, 'min_alpha must be greater than or equal to 0' if min_alpha&.negative?
raise ArgumentError, 'min_numeric must be greater than or equal to 0' if min_numeric&.negative?

if min_alpha.zero? && min_numeric.zero?
return Array.new(char_count) { sample(ALPHANUMS) }.join
end

if min_alpha + min_numeric > char_count
raise ArgumentError, 'min_alpha + min_numeric must be <= number'
end

random_count = char_count - min_alpha - min_numeric

alphas = Array.new(min_alpha) { sample(self::LLetters) }
numbers = Array.new(min_numeric) { sample(self::Numbers) }
randoms = Array.new(random_count) { sample(ALPHANUMS) }

Array.new(char_count) { sample(ALPHANUMS) }.join
combined = alphas + numbers + randoms
combined.shuffle.join
end
end
end
Expand Down
28 changes: 24 additions & 4 deletions lib/faker/default/internet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,25 @@ def username(legacy_specifier = NOT_GIVEN, legacy_separators = NOT_GIVEN, specif
end
end

##
# Produces a randomized string of characters
#
# @param [Integer] min_length
# @param [Integer] max_length
# @param [Boolean] mix_case
# @param [Boolean] special_characters
#
# @return [String]
#
# @example Faker::Internet.password #=> "Vg5mSvY1UeRg7"
# @example Faker::Internet.password(min_length: 8) #=> "YfGjIk0hGzDqS0"
# @example Faker::Internet.password(min_length: 10, max_length: 20) #=> "EoC9ShWd1hWq4vBgFw"
# @example Faker::Internet.password(min_length: 10, max_length: 20, mix_case: true) #=> "3k5qS15aNmG"
# @example Faker::Internet.password(min_length: 10, max_length: 20, mix_case: true, special_characters: true) #=> "*%NkOnJsH4"
#
# @faker.version 2.1.3
# rubocop:disable Metrics/ParameterLists
def password(legacy_min_length = NOT_GIVEN, legacy_max_length = NOT_GIVEN, legacy_mix_case = NOT_GIVEN, legacy_special_characters = NOT_GIVEN, min_length: 8, max_length: 16, mix_case: true, special_characters: false)
# rubocop:enable Metrics/ParameterLists
if legacy_min_length != NOT_GIVEN
warn_with_uplevel 'Passing `min_length` with the 1st argument of `Internet.password` is deprecated. Use keyword argument like `Internet.password(min_length: ...)` instead.', uplevel: 1
min_length = legacy_min_length
Expand All @@ -103,7 +119,8 @@ def password(legacy_min_length = NOT_GIVEN, legacy_max_length = NOT_GIVEN, legac
special_characters = legacy_special_characters
end

temp = Lorem.characters(number: min_length)
min_alpha = mix_case ? 2 : 0
temp = Lorem.characters(number: min_length, min_alpha: min_alpha)
diff_length = max_length - min_length

if diff_length.positive?
Expand All @@ -112,8 +129,12 @@ def password(legacy_min_length = NOT_GIVEN, legacy_max_length = NOT_GIVEN, legac
end

if mix_case
alpha_count = 0
temp.chars.each_with_index do |char, index|
temp[index] = char.upcase if index.even?
if char =~ /[[:alpha:]]/
temp[index] = char.upcase if alpha_count.even?
alpha_count += 1
end
end
end

Expand Down Expand Up @@ -236,7 +257,6 @@ def ip_v6_cidr
"#{ip_v6_address}/#{rand(1..127)}"
end

# rubocop:disable Metrics/ParameterLists
def url(legacy_host = NOT_GIVEN, legacy_path = NOT_GIVEN, legacy_scheme = NOT_GIVEN, host: domain_name, path: "/#{username}", scheme: 'http')
# rubocop:enable Metrics/ParameterLists
if legacy_host != NOT_GIVEN
Expand Down
19 changes: 17 additions & 2 deletions lib/faker/default/lorem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,28 @@ def character
sample(Types::CHARACTERS)
end

def characters(legacy_number = NOT_GIVEN, number: 255)
##
# Produces a random string of alphanumeric characters
#
# @param [Integer] number
# @param [Integer] min_alpha
# @param [Integer] min_numeric
#
# @return [String]
#
# @example Faker::Lorem.characters #=> "uw1ep04lhs0c4d931n1jmrspprf5wrj85fefue0y7y6m56b6omquh7br7dhqijwlawejpl765nb1716idmp3xnfo85v349pzy2o9rir23y2qhflwr71c1585fnynguiphkjm8p0vktwitcsm16lny7jzp9t4drwav3qmhz4yjq4k04x14gl6p148hulyqioo72tf8nwrxxcclfypz2lc58lsibgfe5w5p0xv95peafjjmm2frkhdc6duoky0aha"
# @example Faker::Lorem.characters(number: 10) #=> "ang9cbhoa8"
# @example Faker::Lorem.characters(number: 10, min_alpha: 4) #=> "ang9cbhoa8"
# @example Faker::Lorem.characters(number: 10, min_alpha: 4, min_numeric: 1) #=> "ang9cbhoa8"
#
# @faker.version 2.1.3
def characters(legacy_number = NOT_GIVEN, number: 255, min_alpha: 0, min_numeric: 0)
if legacy_number != NOT_GIVEN
warn_with_uplevel 'Passing `number` with the 1st argument of `Lorem.characters` is deprecated. Use keyword argument like `Lorem.characters(number: ...)` instead.', uplevel: 1
number = legacy_number
end

Alphanumeric.alphanumeric(number: number)
Alphanumeric.alphanumeric(number: number, min_alpha: min_alpha, min_numeric: min_numeric)
end

def multibyte
Expand Down
36 changes: 34 additions & 2 deletions test/faker/default/test_alphanum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,42 @@ def setup
end

def alpha
assert @tester.alpha(characters: 5).match(/[a-z]{5}/)
assert @tester.alpha(number: 5).match(/[a-z]{5}/)
end

def alphanum
assert @tester.alphanumeric(characters: 5).match(/[a-z0-9]{5}/)
assert @tester.alphanumeric(number: 5).match(/[a-z0-9]{5}/)
end

def test_alphanumeric_invalid_min_alpha
assert_raise ArgumentError do
@tester.alphanumeric(number: 5, min_alpha: -1)
end
end

def test_alphanumeric_invalid_min_numeric
assert_raise ArgumentError do
@tester.alphanumeric(number: 5, min_numeric: -1)
end
end

def test_alphanumeric_with_invalid_mins
assert_raise ArgumentError do
@tester.alphanumeric(number: 5, min_numeric: 4, min_alpha: 3)
end
end

def test_alphanumeric_with_min_alpha
letters = @tester.alphanumeric(number: 5, min_alpha: 2).split('').map do |char|
char =~ /[[:alpha:]]/
end
assert letters.compact.size >= 2
end

def test_alphanumeric_with_min_numeric
numbers = @tester.alphanumeric(number: 5, min_numeric: 4).split('').map do |char|
char =~ /[[:digit:]]/
end
assert numbers.compact.size >= 4
end
end
15 changes: 12 additions & 3 deletions test/faker/default/test_faker_internet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ def test_password

def test_password_with_integer_arg
(1..32).each do |min_length|
assert @tester.password(min_length: min_length).length >= min_length
assert @tester.password(min_length: min_length, mix_case: false).length >= min_length
end
end

def test_password_max_with_integer_arg
(1..32).each do |min_length|
max_length = min_length + 4
assert @tester.password(min_length: min_length, max_length: max_length).length <= max_length
assert @tester.password(min_length: min_length, max_length: max_length, mix_case: false).length <= max_length
end
end

Expand All @@ -118,7 +118,16 @@ def test_password_could_achieve_max_length
end

def test_password_with_mixed_case
assert @tester.password.match(/[A-Z]+/)
password = @tester.password
upcase_count = 0
downcase_count = 0
password.chars.each do |char|
if char =~ /[[:alpha:]]/
char.capitalize == char ? upcase_count += 1 : downcase_count += 1
end
end
assert upcase_count >= 1
assert downcase_count >= 1
end

def test_password_without_mixed_case
Expand Down