Skip to content

Commit

Permalink
Fix regex issues: #7, #8, #9
Browse files Browse the repository at this point in the history
  • Loading branch information
bestwebua committed Mar 27, 2019
1 parent 91bafd3 commit 0b7e5d7
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 19 deletions.
1 change: 1 addition & 0 deletions .reek.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ detectors:
FeatureEnvy:
exclude:
- Truemail::Validate::Smtp#not_includes_user_not_found_errors
- Truemail::GenerateEmailHelper#prepare_user_name
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
truemail (0.1.2)
truemail (0.1.3)

GEM
remote: https://rubygems.org/
Expand Down
4 changes: 2 additions & 2 deletions lib/truemail/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ def email_pattern=(regex_pattern)

def verifier_email=(email)
validate_arguments(email, __method__)
@verifier_email = email
@verifier_email = email.downcase
default_verifier_domain
end

def verifier_domain=(domain)
validate_arguments(domain, __method__)
@verifier_domain = domain
@verifier_domain = domain.downcase
end

%i[connection_timeout response_timeout].each do |method|
Expand Down
5 changes: 3 additions & 2 deletions lib/truemail/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ def initialize(current_param, class_name)
end

module RegexConstant
REGEX_DOMAIN = /[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,7}/
REGEX_EMAIL_PATTERN = /(?=\A.{6,255}\z)(\A([\w|\-|\.]+)@(#{REGEX_DOMAIN})\z)/
REGEX_DOMAIN = /[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,24}/i
REGEX_EMAIL_PATTERN = /(?=\A.{6,255}\z)(\A([a-zA-Z0-9]+[\w|\-|\.|\+]*)@(#{REGEX_DOMAIN})\z)/
REGEX_DOMAIN_PATTERN = /(?=\A.{4,255}\z)(\A#{REGEX_DOMAIN}\z)/
REGEX_DOMAIN_FROM_EMAIL = /\A.+@(.+)\z/
end

module Validate
Expand Down
2 changes: 1 addition & 1 deletion lib/truemail/validate/mx.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Mx < Truemail::Validate::Base

def run
return false unless Truemail::Validate::Regex.check(result)
result.domain = result.email[Truemail::RegexConstant::REGEX_EMAIL_PATTERN, 3]
result.domain = result.email[Truemail::RegexConstant::REGEX_DOMAIN_FROM_EMAIL, 1]
return true if success(!result.mail_servers.push(*mx_records).empty?)
add_error(Truemail::Validate::Mx::ERROR)
false
Expand Down
2 changes: 1 addition & 1 deletion lib/truemail/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def initialize(errors: {}, mail_servers: [], **args)
def initialize(email, with: :smtp)
raise ArgumentError.new(with, :argument) unless VALIDATION_TYPES.include?(with)
@validation_type = select_validation_type(email, with)
@result = Result.new(email: email)
@result = Truemail::Validator::Result.new(email: email)
end

def run
Expand Down
2 changes: 1 addition & 1 deletion lib/truemail/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Truemail
VERSION = '0.1.2'
VERSION = '0.1.3'
end
31 changes: 25 additions & 6 deletions spec/support/helpers/generate_email_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def self.call(**options)
new(options).call
end

def initialize(size: :auto, symbols: %w[- _ .], invalid_email_with: [])
def initialize(size: :auto, symbols: %w[- _ . +], invalid_email_with: [])
@size = calculate_email_size(size)
@symbols = symbols
@invalid_symbols = invalid_email_with
Expand All @@ -23,7 +23,7 @@ def call

def calculate_email_size(size)
case size
when :auto then rand(10..250)
when :auto then rand(15..250)
when :min then 1
when :max then 250
when :out_of_range then rand(251..300)
Expand All @@ -36,15 +36,34 @@ def sample_size
size < (symbols_size + invalid_symbols_size + 1) ? 1 : size - symbols_size - invalid_symbols_size - 1
end

def invalid_symbols_empty?
invalid_symbols.empty?
end

def size_one?
size == 1
end

def user_name
@user_name ||=
if size == 1 && !invalid_symbols.empty?
if size_one? && !invalid_symbols_empty?
invalid_symbols.sample
elsif size_one? && invalid_symbols_empty?
('a'..'z').to_a.sample
else
(
('Aa'..'Zz').to_a.shuffle.join.chars.sample(sample_size).push(*symbols.shuffle) << rand(0..9)
).shuffle.push(*invalid_symbols.sample(size)).shuffle[0...size].join
prepare_user_name(randomizer)
end
end

def randomizer
(
('Aa'..'Zz').to_a.shuffle.join.chars.sample(sample_size).push(*symbols.shuffle) << rand(0..9)
).shuffle.push(*invalid_symbols.sample(size)).shuffle[0...size]
end

def prepare_user_name(sample)
sample.rotate!(1) while symbols.include?(sample.first)
sample.join
end
end
end
6 changes: 5 additions & 1 deletion spec/support/helpers/generate_email_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ module Truemail
context 'without params' do
subject(:generate_email) { described_class.call }

let(:allowed_symbols) { %w[@ - _ . +] }

specify { expect(generate_email).to be_an_instance_of(String) }
specify { 100.times { expect(generate_email.size).to be_between(15, 255) } }
specify { 100.times { expect(generate_email).to include(*%w[@ - _ .]) } }
specify { 100.times { expect(generate_email[0]).not_to include(*allowed_symbols) } }
specify { 100.times { expect(generate_email).to include(*allowed_symbols) } }
end

context 'with size: :min' do
specify { expect(described_class.call(size: :min).size).to eq(6) }
specify { expect(described_class.call(size: :min)[0]).to match(/[a-z]/) }
end

context 'with size: :max' do
Expand Down
43 changes: 40 additions & 3 deletions spec/truemail/core_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module Truemail
specify { expect(described_class).to be_const_defined(:REGEX_DOMAIN) }
specify { expect(described_class).to be_const_defined(:REGEX_EMAIL_PATTERN) }
specify { expect(described_class).to be_const_defined(:REGEX_DOMAIN_PATTERN) }
specify { expect(described_class).to be_const_defined(:REGEX_DOMAIN_FROM_EMAIL) }
end

describe 'Truemail::RegexConstant::REGEX_EMAIL_PATTERN' do
Expand All @@ -38,15 +39,34 @@ module Truemail
).to be(false)
end

it "allows '-', '_', '.', numbers, letters case insensitive before @domain" do
it "allows '-', '_', '.', '+', numbers, letters case insensitive before @domain" do
expect(regex_pattern.match?(GenerateEmailHelper.call)).to be(true)
end

it 'allows tld size between 2 and 24 chars' do
expect(regex_pattern.match?('i@i.io')).to be(true)
expect(regex_pattern.match?('i@i.io' + 'z' * 22)).to be(true)
expect(regex_pattern.match?('i@i.io' + 'z' * 23)).to be(false)
expect(regex_pattern.match?('i@i.i')).to be(false)
end

it 'case insensitive' do
%w[h@i.io H@i.io h@I.io h@i.Io H@i.Io Ho@iO.Io].each do |email|
expect(regex_pattern.match?(email)).to be(true)
end
end

it 'not allows special chars' do
expect(
regex_pattern.match?(GenerateEmailHelper.call(invalid_email_with: %w[! ~ , ' & %]))
).to be(false)
end

it "not allows '-', '_', '.', '+' for one char username" do
expect(
regex_pattern.match?(GenerateEmailHelper.call(size: :min, invalid_email_with: %w[- _ . +]))
).to be(false)
end
end

describe 'Truemail::RegexConstant::REGEX_DOMAIN_PATTERN' do
Expand All @@ -70,9 +90,11 @@ module Truemail
expect(regex_pattern.match?('service.subdomain.company.domain')).to be(true)
end

it 'allows tld size between 2 and 7 chars' do
it 'allows tld size between 2 and 24 chars' do
expect(regex_pattern.match?('domain.io')).to be(true)
expect(regex_pattern.match?('domain.rentals')).to be(true)
expect(regex_pattern.match?('domain.iq' + 'z' * 22)).to be(true)
expect(regex_pattern.match?('domain.iq' + 'z' * 23)).to be(false)
expect(regex_pattern.match?('domain')).to be(false)
end

it 'not allows dash as last char' do
Expand All @@ -83,6 +105,21 @@ module Truemail
it 'not allows number in tld' do
expect(regex_pattern.match?('domain.42')).to be(false)
end

it 'case insensitive' do
%w[domain.io DOMAIN.IO Domain.io DoMain.Io].each do |domain|
expect(regex_pattern.match?(domain)).to be(true)
end
end
end

describe 'Truemail::RegexConstant::REGEX_DOMAIN_FROM_EMAIL' do
subject(:regex_pattern) { described_class::REGEX_DOMAIN_FROM_EMAIL }

let(:email) { 'i@domain' }

specify { expect(regex_pattern.match?(email)).to be(true) }
specify { expect(email[regex_pattern, 1]).to eq('domain') }
end
end

Expand Down
5 changes: 4 additions & 1 deletion spec/truemail/validate/mx_spec.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# frozen_string_literal: true

RSpec.describe Truemail::Validate::Mx do
let(:email) { FFaker::Internet.email }

describe 'defined constants' do
specify { expect(described_class).to be_const_defined(:ERROR) }
end

describe '.check' do
subject(:mx_validator) { described_class.check(result_instance) }

let(:email) { FFaker::Internet.email }
let(:result_instance) { Truemail::Validator::Result.new(email: email) }
let(:mx_records_object) { YAML.load(File.open(mx_records_file, 'r')) }

before { Truemail.configure { |config| config.verifier_email = email } }

context 'when validation pass' do
let(:mx_records_file) { "#{File.expand_path('../../', __dir__)}/support/objects/mx_records.yml" }
let(:mail_servers_sorted_by_preference) do
Expand Down

0 comments on commit 0b7e5d7

Please sign in to comment.