-
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
It happens quite often that people typo their email address (I blame phone keyboards for that). Catch common cases in a validator and tell the user that they have a typo in their email. Why yes, I did write the tests for this first, thanks for asking!
- Loading branch information
Showing
3 changed files
with
100 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# frozen_string_literal: true | ||
|
||
class TypoedEmailValidator < ActiveModel::EachValidator | ||
# this array contains "forbidden" email address endings | ||
INVALID_ENDINGS = [ | ||
# without @: | ||
*%w[ | ||
.con | ||
.coom | ||
], | ||
|
||
# with @: | ||
*%w[ | ||
fmail.com | ||
gemail.com | ||
gmail.co | ||
gmaile.com | ||
gmaill.com | ||
icluod.com | ||
proton.mail | ||
].map { "@#{_1}" } | ||
].freeze | ||
|
||
def validate_each(record, attribute, value) | ||
return if valid?(value) | ||
|
||
record.errors[attribute] << "contains a typo" | ||
end | ||
|
||
private | ||
|
||
def valid?(value) | ||
# needs an @ | ||
return false unless value.include?('@') | ||
|
||
# part after the @ needs to have at least one period | ||
return false if value.split('@', 2).last.count('.') == 0 | ||
|
||
# finally, common typos | ||
return false if INVALID_ENDINGS.any? { value.end_with?(_1) } | ||
|
||
true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,61 @@ | |
end | ||
end | ||
|
||
describe 'email validation' do | ||
subject do | ||
FactoryBot.build(:user, email: email).tap(&:validate).errors[:email] | ||
end | ||
|
||
shared_examples_for 'valid email' do |example_email| | ||
context "when email is #{example_email}" do | ||
let(:email) { example_email } | ||
|
||
it "does not have validation errors" do | ||
expect(subject).to be_empty | ||
end | ||
end | ||
end | ||
|
||
shared_examples_for 'invalid email' do |example_email| | ||
context "when email is #{example_email}" do | ||
let(:email) { example_email } | ||
|
||
it "has validation errors" do | ||
expect(subject).not_to be_empty | ||
end | ||
end | ||
end | ||
|
||
include_examples 'valid email', '[email protected]' | ||
include_examples 'valid email', '[email protected]' | ||
include_examples 'valid email', '[email protected]' | ||
include_examples 'valid email', '[email protected]' | ||
include_examples 'valid email', 'fritz.fantom@enterprise.k8s.420stripes.k8s.needs.more.k8s.jira.atlassian.k8s.eu-central-1.s3.amazonaws.com' | ||
include_examples 'invalid email', '@jack' | ||
|
||
# examples from the real world: | ||
|
||
# .con is not a valid TLD | ||
include_examples 'invalid email', '[email protected]' | ||
include_examples 'invalid email', '[email protected]' | ||
# neither is .coom | ||
include_examples 'invalid email', '[email protected]' | ||
# common typos: | ||
include_examples 'invalid email', '[email protected]' | ||
include_examples 'invalid email', '[email protected]' | ||
include_examples 'invalid email', '[email protected]' | ||
include_examples 'invalid email', 'fritz.fantom@gmailcom' | ||
include_examples 'invalid email', '[email protected]' | ||
include_examples 'invalid email', '[email protected]' | ||
include_examples 'invalid email', 'fritz.fantom@hotmailcom' | ||
include_examples 'invalid email', '[email protected]' | ||
# no TLD | ||
include_examples 'invalid email', 'fritz.fantom@gmail' | ||
include_examples 'invalid email', 'fritz.fantom@protonmail' | ||
# not registered as of 2022-01-11 | ||
include_examples 'invalid email', '[email protected]' | ||
end | ||
|
||
# -- User::TimelineMethods -- | ||
|
||
shared_examples_for 'result is blank' do | ||
|