email_validator 1.5.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +85 -0
- data/README.md +168 -18
- data/lib/email_validator.rb +88 -15
- data/spec/email_validator_spec.rb +803 -117
- data/spec/spec_helper.rb +12 -2
- metadata +16 -46
- data/.document +0 -5
- data/.gitignore +0 -22
- data/.travis.yml +0 -7
- data/Changes.md +0 -7
- data/Gemfile +0 -3
- data/Rakefile +0 -10
- data/email_validator.gemspec +0 -23
- data/lib/email_validator/strict.rb +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0bd676f012ed7b109082842ed227bc1881aec6ac24f0e1ed4be24772b206b14f
|
|
4
|
+
data.tar.gz: 6c2f92e0a494f751b690743b15d4d97fd8dd1f9213b8cb2640d6f8f729fca51f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8dd2ab72b087727acec6c7509d3ffa2a51e35074b99113bc8b105c16fc62e9c3288712516e3fc0f15be125d83e0d7db50d368da269672d7ecdddec9ba21f925e
|
|
7
|
+
data.tar.gz: e35ab67f7e7337b1bb1cd04d27d0f47dee128b093cdd6015fdade7967b404441d7abc522dcec18bfda8e682e7ae5418a24ba3a400afa9292b6585e796b644c27
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
This file is used to list changes made in `email_validator`.
|
|
4
|
+
|
|
5
|
+
All notable changes to this project will be documented in this file.
|
|
6
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
7
|
+
|
|
8
|
+
## 2.2.0 (2020-12-09)
|
|
9
|
+
|
|
10
|
+
* [karlwilbur] - Rename `:strict` -> `:rfc`; `:moderate` -> `:strict`
|
|
11
|
+
|
|
12
|
+
## 2.1.0 (2020-12-09)
|
|
13
|
+
|
|
14
|
+
* [karlwilbur] - Add linters and commit hooks to validate code prior to commits
|
|
15
|
+
* [karlwilbur] - Add `:mode` config option; values `:loose`, `:moderate`, `:strict`; default to `:loose`
|
|
16
|
+
* [karlwilbur] - Merge in changes from <https://github.com/karlwilbur/email_validator> fork
|
|
17
|
+
|
|
18
|
+
## 1.9.0.pre (2020-10-14)
|
|
19
|
+
|
|
20
|
+
* [karlwilbur] - Add `require_fqdn` option, require FQDN by default
|
|
21
|
+
* [karlwilbur] - Add support for IPv4 and IPv6 address hosts
|
|
22
|
+
* [karlwilbur] - Add Rubocop, `.editorconfig`; code cleanup/linting
|
|
23
|
+
|
|
24
|
+
## 1.8.0 (2019-06-14)
|
|
25
|
+
|
|
26
|
+
* [karlwilbur] - Refactor class methods for readability
|
|
27
|
+
* [karlwilbur] - `gemspec` meta updates
|
|
28
|
+
* [karlwilbur] - Use POSIX classes for better performance
|
|
29
|
+
* [karlwilbur] - Refactored tests to check specical characters one at a time
|
|
30
|
+
* [karlwilbur] - Refactored validation regex to be more techincally correct
|
|
31
|
+
* [karlwilbur] - Add this `CHANGELOG`
|
|
32
|
+
|
|
33
|
+
## 1.7.0 (2019-04-20)
|
|
34
|
+
|
|
35
|
+
* [karlwilbur] - Added test coverage badge to README
|
|
36
|
+
* [karlwilbur] - Added I18n directive to remove warning message in testing
|
|
37
|
+
* [karlwilbur] - Added RFC-2822 reference
|
|
38
|
+
* [karlwilbur] - Ignore local rspec config file
|
|
39
|
+
* [karlwilbur] - Check for invalid double dots in strict mode
|
|
40
|
+
* [karlwilbur] - Updated spec_helper to remove Code Climate Test Reporter; it is to be run separately now
|
|
41
|
+
* [karlwilbur] - Allow leading/trailing whitespace in normal, not strict
|
|
42
|
+
* [karlwilbur] - Added `invalid?` as inverse of `valid?`
|
|
43
|
+
* [karlwilbur] - Add the ability to limit to a domain
|
|
44
|
+
* [karlwilbur] - Removed CodeShip badge
|
|
45
|
+
* [karlwilbur] - Make the dot in the domain part non-conditional
|
|
46
|
+
* [karlwilbur] - Fix domain label pattern to allow numbers per rfc5321
|
|
47
|
+
|
|
48
|
+
## 1.6.0 (2015-06-14)
|
|
49
|
+
|
|
50
|
+
* [karlwilbur] - Fixed validation to be closer to RFC-5321
|
|
51
|
+
* [karlwilbur] - Updated specs to use Rspec 3 syntax
|
|
52
|
+
* [karlwilbur] - Added unicode suport to validation regexp
|
|
53
|
+
* [karlwilbur] - Added class access to regexp, and `valid?` calss method
|
|
54
|
+
* [karlwilbur] - Simplified code using new methods
|
|
55
|
+
* [karlwilbur] - Added CodeClimate and SimpleCov
|
|
56
|
+
* [karlwilbur] - Updated version and contact info
|
|
57
|
+
|
|
58
|
+
*** Forked from <https://github.com/balexand/email_validator>
|
|
59
|
+
|
|
60
|
+
## 2.0.1 (2019-03-09)
|
|
61
|
+
|
|
62
|
+
* Add email value to error details [f1sherman #50]
|
|
63
|
+
* CI doesn't test Ruby versions that no longer receive updates [f1sherman #51]
|
|
64
|
+
|
|
65
|
+
## 2.0.0 (2019-03-02)
|
|
66
|
+
|
|
67
|
+
* Looser validation [#49]
|
|
68
|
+
|
|
69
|
+
## 1.6.0 (2015-05-12)
|
|
70
|
+
|
|
71
|
+
* Unicode characters support [i7an #24]
|
|
72
|
+
|
|
73
|
+
## 1.5.0 (2014-12-08)
|
|
74
|
+
|
|
75
|
+
* Add a class method for simpler validation [TiteiKo and cluesque #19]
|
|
76
|
+
* RSpec 3.0 syntax [strivedi183 #17]
|
|
77
|
+
* Create Changes.md
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax)
|
|
82
|
+
for help with Markdown.
|
|
83
|
+
|
|
84
|
+
The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/)
|
|
85
|
+
describes the differences between markdown on github and standard markdown.
|
data/README.md
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
# EmailValidator
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](http://travis-ci.com/K-and-R/email_validator)
|
|
4
|
+
[](https://codeclimate.com/github/K-and-R/email_validator)
|
|
5
|
+
[](https://codeclimate.com/github/K-and-R/email_validator/coverage)
|
|
6
|
+
|
|
7
|
+
An email validator for Rails 3+.
|
|
8
|
+
|
|
9
|
+
Supports RFC-2822-compliant and RFC-5321-compliant email validation using RFC-3696 validation.
|
|
10
|
+
|
|
11
|
+
Formerly found at: <https://github.com/balexand/email_validator>
|
|
12
|
+
|
|
13
|
+
## Validation philosophy
|
|
14
|
+
|
|
15
|
+
The default validation provided by this gem (the `:loose` configuration option)
|
|
16
|
+
is extremely loose. It just checks that there's an `@` with something before and
|
|
17
|
+
after it without any whitespace. See [this article by David Gilbertson](https://hackernoon.com/the-100-correct-way-to-validate-email-addresses-7c4818f24643)
|
|
18
|
+
for an explanation of why.
|
|
19
|
+
|
|
20
|
+
We understand that many use cases require an increased level of validation. This
|
|
21
|
+
is supported by using the `:strict` validation mode. Additionally, the `:rfc`
|
|
22
|
+
RFC-compliant mode will consider technically valid emails address as valid which
|
|
23
|
+
may not be wanted, such as the valid `user` or `user@somehost` addresses. These
|
|
24
|
+
would be valid in `:rfc` mode but not valid in `:loose` or `:strict`.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
4
27
|
|
|
5
28
|
Add to your Gemfile:
|
|
6
29
|
|
|
@@ -10,54 +33,181 @@ gem 'email_validator'
|
|
|
10
33
|
|
|
11
34
|
Run:
|
|
12
35
|
|
|
13
|
-
```
|
|
36
|
+
```bash
|
|
14
37
|
bundle install
|
|
15
38
|
```
|
|
16
39
|
|
|
17
|
-
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
Add the following to your model:
|
|
18
43
|
|
|
19
44
|
```ruby
|
|
20
|
-
validates :my_email_attribute, :
|
|
45
|
+
validates :my_email_attribute, email: true
|
|
21
46
|
```
|
|
22
47
|
|
|
23
|
-
|
|
48
|
+
You may wish to allow domains without a FDQN, like `user@somehost`. While this
|
|
49
|
+
is technically a valid address, it is uncommon to consider such address valid.
|
|
50
|
+
We will consider them valid by default with the `:loose` checking. Disallowed
|
|
51
|
+
by setting `require_fqdn: true` or by enabling `:strict` checking:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
validates :my_email_attribute, email: {mode: :strict, require_fqdn: true}
|
|
55
|
+
```
|
|
24
56
|
|
|
25
|
-
|
|
57
|
+
You can also limit to a single domain (e.g: this might help if, for example, you
|
|
58
|
+
have separate `User` and `AdminUser` models and want to ensure that `AdminUser`
|
|
59
|
+
emails are on a specific domain):
|
|
26
60
|
|
|
27
61
|
```ruby
|
|
28
|
-
|
|
62
|
+
validates :my_email_attribute, email: {domain: 'example.com'}
|
|
29
63
|
```
|
|
30
64
|
|
|
31
|
-
|
|
65
|
+
## Configuration
|
|
66
|
+
|
|
67
|
+
Default configuration can be overridden by setting options in `config/initializers/email_validator.rb`:
|
|
32
68
|
|
|
33
69
|
```ruby
|
|
34
|
-
|
|
70
|
+
if defined?(EmailValidator)
|
|
71
|
+
# To completly override the defaults
|
|
72
|
+
EmailValidator.default_options = {
|
|
73
|
+
allow_nil: false,
|
|
74
|
+
domain: nil,
|
|
75
|
+
require_fqdn: nil,
|
|
76
|
+
mode: :loose
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# or just a few options
|
|
80
|
+
EmailValidator.default_options.merge!({ domain: 'mydomain.com' })
|
|
81
|
+
end
|
|
35
82
|
```
|
|
36
83
|
|
|
84
|
+
### Loose mode
|
|
85
|
+
|
|
86
|
+
This it the default validation mode of this gem. It is intentionally extremely
|
|
87
|
+
loose (see the [Validation Philosophy section](#validation_philosophy) above. It
|
|
88
|
+
just checks that there's an `@` with something before and after it without any
|
|
89
|
+
whitespace.
|
|
90
|
+
|
|
91
|
+
### Strict mode
|
|
92
|
+
|
|
93
|
+
Enabling `:strict` checking will check for a "normal" email format that would
|
|
94
|
+
be expected in most common everyday usage. Strict mode basically checks for a
|
|
95
|
+
properly sized and formatted mailbox label, a single "@" symbol, and a properly
|
|
96
|
+
sized and formatted FQDN. Enabling `:strict` mode will also enable `:require_fqdn`
|
|
97
|
+
configuration option.
|
|
98
|
+
|
|
99
|
+
Strict mode can be enabled globally by requiring `email_validator/strict` in
|
|
100
|
+
your `Gemfile`, by setting the option in `config/initializers/email_validator.rb`,
|
|
101
|
+
or by specifying the option in a specific `validates` call.
|
|
102
|
+
|
|
103
|
+
* `Gemfile`:
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
gem 'email_validator', require: 'email_validator/strict'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
* `config/initializers/email_validator.rb`:
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
if defined?(EmailValidator)
|
|
113
|
+
EmailValidator.default_options[:mode] = :strict
|
|
114
|
+
end
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
* `validates` call:
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
validates :my_email_attribute, email: {mode: :strict}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### RFC mode
|
|
124
|
+
|
|
125
|
+
In order to have RFC-compliant validation (according to [http://www.remote.org/jochen/mail/info/chars.html](https://web.archive.org/web/20150508102948/http://www.remote.org/jochen/mail/info/chars.html)),
|
|
126
|
+
enable `:rfc` mode.
|
|
127
|
+
|
|
128
|
+
You can do this globally by requiring `email_validator/rfc` in your `Gemfile`,
|
|
129
|
+
by setting the options in `config/initializers/email_validator.rb`, or you can do
|
|
130
|
+
this in a specific `validates` call.
|
|
131
|
+
|
|
132
|
+
* `Gemfile`:
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
gem 'email_validator', require: 'email_validator/rfc'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
* `config/initializers/email_validator.rb`:
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
if defined?(EmailValidator)
|
|
142
|
+
EmailValidator.default_options[:mode] = :rfc
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
* `validates` call:
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
validates :my_email_attribute, email: {mode: :rfc}
|
|
150
|
+
```
|
|
151
|
+
|
|
37
152
|
## Validation outside a model
|
|
38
153
|
|
|
39
|
-
If you need to validate an email outside a model, you can get the regexp
|
|
154
|
+
If you need to validate an email outside a model, you can get the regexp:
|
|
40
155
|
|
|
41
|
-
###
|
|
156
|
+
### Loose/default mode
|
|
42
157
|
|
|
43
158
|
```ruby
|
|
44
|
-
EmailValidator.regexp # returns the regex
|
|
45
159
|
EmailValidator.valid?('narf@example.com') # boolean
|
|
46
160
|
```
|
|
47
161
|
|
|
162
|
+
### Requiring a FQDN
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
EmailValidator.valid?('narf@somehost') # boolean false
|
|
166
|
+
EmailValidator.invalid?('narf@somehost', require_fqdn: false) # boolean true
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Requiring a specific domain
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
EmailValidator.valid?('narf@example.com', domain: 'foo.com') # boolean false
|
|
173
|
+
EmailValidator.invalid?('narf@example.com', domain: 'foo.com') # boolean true
|
|
174
|
+
```
|
|
175
|
+
|
|
48
176
|
### Strict mode
|
|
49
177
|
|
|
50
178
|
```ruby
|
|
51
|
-
EmailValidator.regexp(:
|
|
179
|
+
EmailValidator.regexp(mode: :strict) # returns the regex
|
|
180
|
+
EmailValidator.valid?('narf@example.com', mode: :strict) # boolean
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### RFC mode
|
|
184
|
+
|
|
185
|
+
```ruby
|
|
186
|
+
EmailValidator.regexp(mode: :rfc) # returns the regex
|
|
187
|
+
EmailValidator.valid?('narf@example.com', mode: :rfc) # boolean
|
|
52
188
|
```
|
|
53
189
|
|
|
54
190
|
## Thread safety
|
|
55
191
|
|
|
56
|
-
This gem is thread safe, with one caveat: `EmailValidator.default_options` must
|
|
192
|
+
This gem is thread safe, with one caveat: `EmailValidator.default_options` must
|
|
193
|
+
be configured before use in a multi-threaded environment. If you configure
|
|
194
|
+
`default_options` in a Rails initializer file, then you're good to go since
|
|
195
|
+
initializers are run before worker threads are spawned.
|
|
196
|
+
|
|
197
|
+
## Alternative gems
|
|
198
|
+
|
|
199
|
+
Do you prefer a different email validation gem? If so, open an issue with a brief
|
|
200
|
+
explanation of how it differs from this gem. I'll add a link to it in this README.
|
|
201
|
+
|
|
202
|
+
* [`email_address`](https://github.com/afair/email_address) (<https://github.com/K-and-R/email_validator/issues/58>)
|
|
203
|
+
* [`email_verifier`](https://github.com/kamilc/email_verifier) (<https://github.com/K-and-R/email_validator/issues/65>)
|
|
57
204
|
|
|
58
|
-
##
|
|
205
|
+
## Maintainers
|
|
59
206
|
|
|
60
|
-
|
|
207
|
+
All thanks is given to [Brian Alexander (balexand)](https://github.com/balexand)
|
|
208
|
+
for is initial work on this gem.
|
|
61
209
|
|
|
62
|
-
|
|
210
|
+
Currently maintained by:
|
|
63
211
|
|
|
212
|
+
* Karl Wilbur (<https://github.com/karlwilbur>)
|
|
213
|
+
* K&R Software (<https://github.com/K-and-R>)
|
data/lib/email_validator.rb
CHANGED
|
@@ -1,28 +1,101 @@
|
|
|
1
1
|
# Based on work from http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/
|
|
2
2
|
class EmailValidator < ActiveModel::EachValidator
|
|
3
|
-
|
|
3
|
+
# rubocop:disable Style/ClassVars
|
|
4
|
+
@@default_options = {
|
|
5
|
+
:allow_nil => false,
|
|
6
|
+
:domain => nil,
|
|
7
|
+
:require_fqdn => nil,
|
|
8
|
+
:mode => :loose
|
|
9
|
+
}
|
|
10
|
+
# rubocop:enable Style/ClassVars
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
class << self
|
|
13
|
+
def default_options
|
|
14
|
+
@@default_options
|
|
15
|
+
end
|
|
7
16
|
|
|
8
|
-
|
|
17
|
+
def valid?(value, options = {})
|
|
18
|
+
options = parse_options(options)
|
|
19
|
+
return true if value.nil? && options[:allow_nil] == true
|
|
20
|
+
return false if value.nil?
|
|
21
|
+
!!(value =~ regexp(options))
|
|
22
|
+
end
|
|
9
23
|
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
def invalid?(value, options = {})
|
|
25
|
+
!valid?(value, options)
|
|
26
|
+
end
|
|
12
27
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
# Refs:
|
|
29
|
+
# https://tools.ietf.org/html/rfc2822 : 3.2. Lexical Tokens, 3.4.1. Addr-spec specification
|
|
30
|
+
# https://tools.ietf.org/html/rfc5321 : 4.1.2. Command Argument Syntax
|
|
31
|
+
def regexp(options = {})
|
|
32
|
+
options = parse_options(options)
|
|
33
|
+
if options[:mode] == :loose
|
|
34
|
+
return /\A[^\s]+@[^\s]+\z/ if options[:domain].nil?
|
|
35
|
+
return /\A[^\s]+@#{domain_pattern(options)}\z/
|
|
36
|
+
end
|
|
37
|
+
/\A(?>#{local_part_pattern})@#{domain_pattern(options)}\z/i
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
protected
|
|
41
|
+
|
|
42
|
+
def alpha
|
|
43
|
+
'[[:alpha:]]'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def alnum
|
|
47
|
+
'[[:alnum:]]'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def alnumhy
|
|
51
|
+
"(?:#{alnum}|-)"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def ipv4
|
|
55
|
+
'\d{1,3}(?:\.\d{1,3}){3}'
|
|
56
|
+
end
|
|
16
57
|
|
|
17
|
-
|
|
18
|
-
|
|
58
|
+
def ipv6
|
|
59
|
+
# only supporting full IPv6 addresses right now
|
|
60
|
+
'IPv6:[[:xdigit:]]{1,4}(?::[[:xdigit:]]{1,4}){7}'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def address_literal
|
|
64
|
+
"\\[(?:#{ipv4}|#{ipv6})\\]"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def label_pattern
|
|
68
|
+
"#{alpha}(?:#{alnumhy}{,62}#{alnum})?"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def atom_char
|
|
72
|
+
# The `atext` spec
|
|
73
|
+
# We are looking at this without whitespace; no whitespace support here
|
|
74
|
+
"[-#{alpha}#{alnum}+_!\"'#$%^&*{}/=?`|~]"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def local_part_pattern
|
|
78
|
+
# the `dot-atom-text` spec, but with a 64 character limit
|
|
79
|
+
"#{atom_char}(?:\\.?#{atom_char}){,63}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def domain_pattern(options)
|
|
83
|
+
return options[:domain].sub(/\./, '\.') if options[:domain].present?
|
|
84
|
+
return "(?:#{label_pattern}\\.)+#{label_pattern}" if options[:require_fqdn]
|
|
85
|
+
"(?:#{address_literal}|(?:#{label_pattern}\\.)*#{label_pattern})"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
def parse_options(options)
|
|
91
|
+
# `:strict` mode enables `:require_fqdn`, unless it is already explicitly disabled
|
|
92
|
+
options[:require_fqdn] = true if options[:require_fqdn].nil? && options[:mode] == :strict
|
|
93
|
+
default_options.merge(options)
|
|
94
|
+
end
|
|
19
95
|
end
|
|
20
96
|
|
|
21
97
|
def validate_each(record, attribute, value)
|
|
22
98
|
options = @@default_options.merge(self.options)
|
|
23
|
-
|
|
24
|
-
unless self.class.valid?(value, self.options)
|
|
25
|
-
record.errors.add(attribute, options[:message] || :invalid)
|
|
26
|
-
end
|
|
99
|
+
record.errors.add(attribute, options[:message] || :invalid) unless self.class.valid?(value, options)
|
|
27
100
|
end
|
|
28
101
|
end
|
|
@@ -1,198 +1,884 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
class
|
|
3
|
+
class DefaultUser < TestModel
|
|
4
4
|
validates :email, :email => true
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
class StrictUser < TestModel
|
|
8
|
-
validates :email, :email => {:
|
|
8
|
+
validates :email, :email => { :mode => :strict }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
class
|
|
12
|
-
validates :email, :email => {:
|
|
11
|
+
class RfcUser < TestModel
|
|
12
|
+
validates :email, :email => { :mode => :rfc }
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
class
|
|
16
|
-
validates :email, :email => {:allow_nil =>
|
|
15
|
+
class AllowNilDefaultUser < TestModel
|
|
16
|
+
validates :email, :email => { :allow_nil => true }
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
class
|
|
20
|
-
validates :
|
|
19
|
+
class AllowNilStrictUser < TestModel
|
|
20
|
+
validates :email, :email => { :allow_nil => true, :mode => :strict }
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
class AllowNilRfcUser < TestModel
|
|
24
|
+
validates :email, :email => { :allow_nil => true, :mode => :rfc }
|
|
25
|
+
end
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"uncommon-tld@sld.museum",
|
|
41
|
-
"uncommon-tld@sld.travel",
|
|
42
|
-
"uncommon-tld@sld.mobi",
|
|
43
|
-
"country-code-tld@sld.uk",
|
|
44
|
-
"country-code-tld@sld.rw",
|
|
45
|
-
"local@sld.newTLD",
|
|
46
|
-
"local@sub.domains.com",
|
|
47
|
-
"aaa@bbb.co.jp",
|
|
48
|
-
"nigel.worthington@big.co.uk",
|
|
49
|
-
"f@c.com",
|
|
50
|
-
"areallylongnameaasdfasdfasdfasdf@asdfasdfasdfasdfasdf.ab.cd.ef.gh.co.ca"
|
|
51
|
-
].each do |email|
|
|
27
|
+
class DisallowNilDefaultUser < TestModel
|
|
28
|
+
validates :email, :email => { :allow_nil => false }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class DisallowNilStrictUser < TestModel
|
|
32
|
+
validates :email, :email => { :allow_nil => false, :mode => :strict }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class DisallowNilRfcUser < TestModel
|
|
36
|
+
validates :email, :email => { :allow_nil => false, :mode => :rfc }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class DomainStrictUser < TestModel
|
|
40
|
+
validates :email, :email => { :domain => 'example.com', :mode => :strict }
|
|
41
|
+
end
|
|
52
42
|
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
class DomainRfcUser < TestModel
|
|
44
|
+
validates :email, :email => { :domain => 'example.com', :mode => :rfc }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class NonFqdnStrictUser < TestModel
|
|
48
|
+
validates :email, :email => { :require_fqdn => false, :mode => :strict }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class NonFqdnRfcUser < TestModel
|
|
52
|
+
validates :email, :email => { :require_fqdn => false, :mode => :rfc }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class DefaultUserWithMessage < TestModel
|
|
56
|
+
validates :email_address, :email => { :message => 'is not looking very good!' }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
RSpec.describe EmailValidator do
|
|
60
|
+
describe 'validation' do
|
|
61
|
+
valid_special_chars = {
|
|
62
|
+
:ampersand => '&',
|
|
63
|
+
:asterisk => '*',
|
|
64
|
+
:backtick => '`',
|
|
65
|
+
:braceleft => '{',
|
|
66
|
+
:braceright => '}',
|
|
67
|
+
:caret => '^',
|
|
68
|
+
:dollar => '$',
|
|
69
|
+
:equals => '=',
|
|
70
|
+
:exclaim => '!',
|
|
71
|
+
:hash => '#',
|
|
72
|
+
:hyphen => '-',
|
|
73
|
+
:percent => '%',
|
|
74
|
+
:plus => '+',
|
|
75
|
+
:pipe => '|',
|
|
76
|
+
:question => '?',
|
|
77
|
+
:quotedouble => '"',
|
|
78
|
+
:quotesingle => "'",
|
|
79
|
+
:slash => '/',
|
|
80
|
+
:tilde => '~',
|
|
81
|
+
:underscore => '_'
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
invalid_special_chars = {
|
|
85
|
+
:backslash => '\\',
|
|
86
|
+
:braketleft => '[',
|
|
87
|
+
:braketright => ']',
|
|
88
|
+
:colon => ':',
|
|
89
|
+
:comma => ',',
|
|
90
|
+
:greater => '>',
|
|
91
|
+
:lesser => '<',
|
|
92
|
+
:parenleft => '(',
|
|
93
|
+
:parenright => ')',
|
|
94
|
+
:semicolon => ';'
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
valid_includable = valid_special_chars.merge({ :dot => '.' })
|
|
98
|
+
valid_beginable = valid_special_chars
|
|
99
|
+
valid_endable = valid_special_chars
|
|
100
|
+
invalid_includable = { :at => '@' }
|
|
101
|
+
whitespace = { :newline => "\n", :tab => "\t", :carriage_return => "\r", :space => ' ' }
|
|
102
|
+
strictly_invalid_includable = invalid_special_chars
|
|
103
|
+
strictly_invalid_beginable = strictly_invalid_includable.merge({ :dot => '.' })
|
|
104
|
+
strictly_invalid_endable = strictly_invalid_beginable
|
|
105
|
+
domain_invalid_beginable = invalid_special_chars.merge(valid_special_chars)
|
|
106
|
+
domain_invalid_endable = domain_invalid_beginable
|
|
107
|
+
domain_invalid_includable = domain_invalid_beginable.reject { |k, _v| k == :hyphen }
|
|
108
|
+
|
|
109
|
+
# rubocop:disable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain
|
|
110
|
+
context 'when given the valid email' do
|
|
111
|
+
valid_includable.map { |k, v| [
|
|
112
|
+
"include-#{v}-#{k}@valid-characters-in-local.dev"
|
|
113
|
+
]}.concat(valid_beginable.map { |k, v| [
|
|
114
|
+
"#{v}start-with-#{k}@valid-characters-in-local.dev"
|
|
115
|
+
]}).concat(valid_endable.map { |k, v| [
|
|
116
|
+
"end-with-#{k}-#{v}@valid-characters-in-local.dev"
|
|
117
|
+
]}).concat([
|
|
118
|
+
'a+b@plus-in-local.com',
|
|
119
|
+
'a_b@underscore-in-local.com',
|
|
120
|
+
'user@example.com',
|
|
121
|
+
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@letters-in-local.dev',
|
|
122
|
+
'01234567890@numbers-in-local.dev',
|
|
123
|
+
'a@single-character-in-local.dev',
|
|
124
|
+
'one-character-third-level@a.example.com',
|
|
125
|
+
'single-character-in-sld@x.dev',
|
|
126
|
+
'local@dash-in-sld.com',
|
|
127
|
+
'numbers-in-sld@s123.com',
|
|
128
|
+
'one-letter-sld@x.dev',
|
|
129
|
+
'uncommon-tld@sld.museum',
|
|
130
|
+
'uncommon-tld@sld.travel',
|
|
131
|
+
'uncommon-tld@sld.mobi',
|
|
132
|
+
'country-code-tld@sld.uk',
|
|
133
|
+
'country-code-tld@sld.rw',
|
|
134
|
+
'local@sld.newTLD',
|
|
135
|
+
'local@sub.domains.com',
|
|
136
|
+
'aaa@bbb.co.jp',
|
|
137
|
+
'nigel.worthington@big.co.uk',
|
|
138
|
+
'f@c.com',
|
|
139
|
+
'f@s.c',
|
|
140
|
+
'someuser@somehost.somedomain',
|
|
141
|
+
'mixed-1234-in-{+^}-local@sld.dev',
|
|
142
|
+
'partially."quoted"@sld.com',
|
|
143
|
+
'areallylongnameaasdfasdfasdfasdf@asdfasdfasdfasdfasdf.ab.cd.ef.gh.co.ca'
|
|
144
|
+
]).flatten.each do |email|
|
|
145
|
+
context 'when using defaults' do
|
|
146
|
+
it "'#{email}' should be valid" do
|
|
147
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
151
|
+
expect(described_class).to be_valid(email)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
155
|
+
expect(described_class).not_to be_invalid(email)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "'#{email}' should match the regexp" do
|
|
159
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
160
|
+
end
|
|
55
161
|
end
|
|
56
162
|
|
|
57
|
-
|
|
58
|
-
|
|
163
|
+
context 'when in `:strict` mode' do
|
|
164
|
+
it "'#{email}' should be valid" do
|
|
165
|
+
expect(StrictUser.new(:email => email)).to be_valid
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
169
|
+
expect(described_class).to be_valid(email, :mode => :strict)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "'#{email}' should not be invalid using EmailValidator.valid?" do
|
|
173
|
+
expect(described_class).not_to be_invalid(email, :mode => :strict)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "'#{email}' should match the regexp" do
|
|
177
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true)
|
|
178
|
+
end
|
|
59
179
|
end
|
|
60
180
|
|
|
61
|
-
|
|
62
|
-
|
|
181
|
+
context 'when in `:rfc` mode' do
|
|
182
|
+
it "'#{email}' should be valid" do
|
|
183
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
187
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
191
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "'#{email}' should match the regexp" do
|
|
195
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
196
|
+
end
|
|
63
197
|
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
64
200
|
|
|
65
|
-
|
|
66
|
-
|
|
201
|
+
context 'when given the valid host-only email' do
|
|
202
|
+
[
|
|
203
|
+
'f@s',
|
|
204
|
+
'user@localhost',
|
|
205
|
+
'someuser@somehost'
|
|
206
|
+
].each do |email|
|
|
207
|
+
context 'when using defaults' do
|
|
208
|
+
it "'#{email}' should be valid" do
|
|
209
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
213
|
+
expect(described_class).to be_valid(email)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
217
|
+
expect(described_class).not_to be_invalid(email)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "'#{email}' should match the regexp" do
|
|
221
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
222
|
+
end
|
|
67
223
|
end
|
|
68
224
|
|
|
69
|
-
|
|
70
|
-
|
|
225
|
+
context 'when in `:strict` mode' do
|
|
226
|
+
it "'#{email}' should not be valid" do
|
|
227
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
231
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
235
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "'#{email}' should not match the regexp" do
|
|
239
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
240
|
+
end
|
|
71
241
|
end
|
|
72
242
|
|
|
73
|
-
|
|
243
|
+
context 'when in `:rfc` mode' do
|
|
244
|
+
it "'#{email}' should be valid" do
|
|
245
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
249
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
250
|
+
end
|
|
74
251
|
|
|
252
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
253
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
it "'#{email}' should match the regexp" do
|
|
257
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
75
261
|
end
|
|
76
262
|
|
|
77
|
-
context
|
|
263
|
+
context 'when given the valid IP address email' do
|
|
78
264
|
[
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"f@s.c",
|
|
82
|
-
"@bar.com",
|
|
83
|
-
"test@example.com@example.com",
|
|
84
|
-
"test@",
|
|
85
|
-
"@missing-local.org",
|
|
86
|
-
"a b@space-in-local.com",
|
|
87
|
-
"! \#$%\`|@invalid-characters-in-local.org",
|
|
88
|
-
"<>@[]\`|@even-more-invalid-characters-in-local.org",
|
|
89
|
-
"missing-sld@.com",
|
|
90
|
-
"invalid-characters-in-sld@! \"\#$%(),/;<>_[]\`|.org",
|
|
91
|
-
"missing-dot-before-tld@com",
|
|
92
|
-
"missing-tld@sld.",
|
|
93
|
-
" ",
|
|
94
|
-
"missing-at-sign.net",
|
|
95
|
-
"unbracketed-IP@127.0.0.1",
|
|
96
|
-
"invalid-ip@127.0.0.1.26",
|
|
97
|
-
"another-invalid-ip@127.0.0.256",
|
|
98
|
-
"IP-and-port@127.0.0.1:25",
|
|
99
|
-
"the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.net",
|
|
100
|
-
"user@example.com\n<script>alert('hello')</script>"
|
|
265
|
+
'bracketed-IP@[127.0.0.1]',
|
|
266
|
+
'bracketed-and-labeled-IPv6@[IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678]'
|
|
101
267
|
].each do |email|
|
|
268
|
+
context 'when using defaults' do
|
|
269
|
+
it "'#{email}' should be valid" do
|
|
270
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
274
|
+
expect(described_class).to be_valid(email)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
278
|
+
expect(described_class).not_to be_invalid(email)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it "'#{email}' should match the regexp" do
|
|
282
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
context 'when in `:strict` mode' do
|
|
287
|
+
it "'#{email}' should not be valid" do
|
|
288
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
292
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
296
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
297
|
+
end
|
|
102
298
|
|
|
103
|
-
|
|
104
|
-
|
|
299
|
+
it "'#{email}' should not match the regexp" do
|
|
300
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
301
|
+
end
|
|
105
302
|
end
|
|
106
303
|
|
|
107
|
-
|
|
108
|
-
|
|
304
|
+
context 'when in `:rfc` mode' do
|
|
305
|
+
it "'#{email}' should be valid" do
|
|
306
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
310
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
314
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "'#{email}' should match the regexp" do
|
|
318
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
context 'when given the invalid email' do
|
|
325
|
+
invalid_includable.map { |k, v| [
|
|
326
|
+
"include-#{v}-#{k}@invalid-characters-in-local.dev"
|
|
327
|
+
]}.concat(domain_invalid_beginable.map { |k, v| [
|
|
328
|
+
"start-with-#{k}@#{v}invalid-characters-in-domain.dev"
|
|
329
|
+
]}).concat(domain_invalid_endable.map { |k, v| [
|
|
330
|
+
"end-with-#{k}@invalid-characters-in-domain#{v}.dev"
|
|
331
|
+
]}).concat(domain_invalid_includable.map { |k, v| [
|
|
332
|
+
"include-#{k}@invalid-characters-#{v}-in-domain.dev"
|
|
333
|
+
]}).concat([
|
|
334
|
+
'test@example.com@example.com',
|
|
335
|
+
'missing-sld@.com',
|
|
336
|
+
'missing-tld@sld.',
|
|
337
|
+
'only-numbers-in-domain-label@sub.123.com',
|
|
338
|
+
'only-numbers-in-domain-label@123.example.com',
|
|
339
|
+
'unbracketed-IPv6@abcd:ef01:1234:5678:9abc:def0:1234:5678',
|
|
340
|
+
'unbracketed-and-labled-IPv6@IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678',
|
|
341
|
+
'bracketed-and-unlabeled-IPv6@[abcd:ef01:1234:5678:9abc:def0:1234:5678]',
|
|
342
|
+
'unbracketed-IPv4@127.0.0.1',
|
|
343
|
+
'invalid-IPv4@127.0.0.1.26',
|
|
344
|
+
'another-invalid-IPv4@127.0.0.256',
|
|
345
|
+
'IPv4-and-port@127.0.0.1:25',
|
|
346
|
+
'host-beginning-with-dot@.example.com',
|
|
347
|
+
'domain-beginning-with-dash@-example.com',
|
|
348
|
+
'domain-ending-with-dash@example-.com',
|
|
349
|
+
'the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.dev',
|
|
350
|
+
"user@example.com<script>alert('hello')</script>"
|
|
351
|
+
]).flatten.each do |email|
|
|
352
|
+
context 'when using defaults' do
|
|
353
|
+
it "'#{email}' should be valid" do
|
|
354
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
358
|
+
expect(described_class).to be_valid(email)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
362
|
+
expect(described_class).not_to be_invalid(email)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
it "'#{email}' should match the regexp" do
|
|
366
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
context 'when in `:strict` mode' do
|
|
371
|
+
it "'#{email}' should not be valid" do
|
|
372
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
376
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
380
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it "'#{email}' should not match the regexp" do
|
|
384
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
385
|
+
end
|
|
109
386
|
end
|
|
110
387
|
|
|
111
|
-
|
|
112
|
-
|
|
388
|
+
context 'when in `:rfc` mode' do
|
|
389
|
+
it "'#{email}' should not be valid" do
|
|
390
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
394
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
398
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
it "'#{email}' should not match the regexp" do
|
|
402
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
403
|
+
end
|
|
113
404
|
end
|
|
405
|
+
end
|
|
406
|
+
end
|
|
114
407
|
|
|
115
|
-
|
|
116
|
-
|
|
408
|
+
context 'when given the invalid email with whitespace in parts' do
|
|
409
|
+
whitespace.map { |k, v| [
|
|
410
|
+
"include-#{v}-#{k}@invalid-characters-in-local.dev"
|
|
411
|
+
]}.concat([
|
|
412
|
+
'foo @bar.com',
|
|
413
|
+
"foo\t@bar.com",
|
|
414
|
+
"foo\n@bar.com",
|
|
415
|
+
"foo\r@bar.com",
|
|
416
|
+
'test@ example.com',
|
|
417
|
+
'user@example .com',
|
|
418
|
+
"user@example\t.com",
|
|
419
|
+
"user@example\n.com",
|
|
420
|
+
"user@example\r.com",
|
|
421
|
+
'user@exam ple.com',
|
|
422
|
+
"user@exam\tple.com",
|
|
423
|
+
"user@exam\nple.com",
|
|
424
|
+
"user@exam\rple.com",
|
|
425
|
+
'us er@example.com',
|
|
426
|
+
"us\ter@example.com",
|
|
427
|
+
"us\ner@example.com",
|
|
428
|
+
"us\rer@example.com",
|
|
429
|
+
"user@example.com\n<script>alert('hello')</script>",
|
|
430
|
+
"user@example.com\t<script>alert('hello')</script>",
|
|
431
|
+
"user@example.com\r<script>alert('hello')</script>",
|
|
432
|
+
"user@example.com <script>alert('hello')</script>",
|
|
433
|
+
' leading-whitespace@example.com',
|
|
434
|
+
'trailing-whitespace@example.com ',
|
|
435
|
+
' leading-and-trailing-whitespace@example.com ',
|
|
436
|
+
' user-with-leading-whitespace-space@example.com',
|
|
437
|
+
"\tuser-with-leading-whitespace-tab@example.com",
|
|
438
|
+
"
|
|
439
|
+
user-with-leading-whitespace-newline@example.com",
|
|
440
|
+
'domain-with-trailing-whitespace-space@example.com ',
|
|
441
|
+
"domain-with-trailing-whitespace-tab@example.com\t",
|
|
442
|
+
"domain-with-trailing-whitespace-newline@example.com
|
|
443
|
+
"
|
|
444
|
+
]).flatten.each do |email|
|
|
445
|
+
context 'when using defaults' do
|
|
446
|
+
it "'#{email}' should not be valid" do
|
|
447
|
+
expect(DefaultUser.new(:email => email)).not_to be_valid
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
451
|
+
expect(described_class).not_to be_valid(email)
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
455
|
+
expect(described_class).to be_invalid(email)
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
it "'#{email}' should not match the regexp" do
|
|
459
|
+
expect(!!(email =~ described_class.regexp)).to be(false)
|
|
460
|
+
end
|
|
117
461
|
end
|
|
118
462
|
|
|
119
|
-
|
|
120
|
-
|
|
463
|
+
context 'when in `:strict` mode' do
|
|
464
|
+
it "'#{email}' should not be valid" do
|
|
465
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
469
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
473
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
it "'#{email}' should not match the regexp" do
|
|
477
|
+
expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
478
|
+
end
|
|
121
479
|
end
|
|
122
480
|
|
|
481
|
+
context 'when in `:rfc` mode' do
|
|
482
|
+
it "'#{email}' should not be valid" do
|
|
483
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
487
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
491
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it "'#{email}' should not match the regexp" do
|
|
495
|
+
expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
496
|
+
end
|
|
497
|
+
end
|
|
123
498
|
end
|
|
124
499
|
end
|
|
125
500
|
|
|
126
|
-
context
|
|
501
|
+
context 'when given the invalid email with missing parts' do
|
|
127
502
|
[
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
503
|
+
'',
|
|
504
|
+
'@bar.com',
|
|
505
|
+
'test@',
|
|
506
|
+
'@missing-local.dev',
|
|
507
|
+
' ',
|
|
508
|
+
'missing-at-sign.dev'
|
|
134
509
|
].each do |email|
|
|
510
|
+
context 'when using defaults' do
|
|
511
|
+
it "'#{email}' should not be valid" do
|
|
512
|
+
expect(DefaultUser.new(:email => email)).not_to be_valid
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
516
|
+
expect(described_class).not_to be_valid(email)
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
520
|
+
expect(described_class).to be_invalid(email)
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
it "'#{email}' should not match the regexp" do
|
|
524
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(false)
|
|
525
|
+
end
|
|
526
|
+
end
|
|
135
527
|
|
|
136
|
-
|
|
137
|
-
|
|
528
|
+
context 'when in `:strict` mode' do
|
|
529
|
+
it "'#{email}' should not be valid" do
|
|
530
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
534
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
538
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
it "'#{email}' should not match the regexp" do
|
|
542
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
543
|
+
end
|
|
138
544
|
end
|
|
139
545
|
|
|
140
|
-
|
|
141
|
-
|
|
546
|
+
context 'when in `:rfc` mode' do
|
|
547
|
+
it "'#{email}' should not be valid" do
|
|
548
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
552
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
556
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
it "'#{email}' should not match the regexp" do
|
|
560
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
561
|
+
end
|
|
142
562
|
end
|
|
563
|
+
end
|
|
564
|
+
end
|
|
143
565
|
|
|
144
|
-
|
|
145
|
-
|
|
566
|
+
context 'when given the strictly invalid email' do
|
|
567
|
+
strictly_invalid_includable.map { |k, v| [
|
|
568
|
+
"include-#{v}-#{k}@invalid-characters-in-local.dev"
|
|
569
|
+
]}.concat(strictly_invalid_beginable.map { |k, v| [
|
|
570
|
+
"#{v}start-with-#{k}@invalid-characters-in-local.dev"
|
|
571
|
+
]}).concat(strictly_invalid_endable.map { |k, v| [
|
|
572
|
+
"end-with-#{k}#{v}@invalid-characters-in-local.dev"
|
|
573
|
+
]}).concat([
|
|
574
|
+
'user..-with-double-dots@example.com',
|
|
575
|
+
'.user-beginning-with-dot@example.com',
|
|
576
|
+
'user-ending-with-dot.@example.com'
|
|
577
|
+
]).flatten.each do |email|
|
|
578
|
+
context 'when using defaults' do
|
|
579
|
+
it "#{email.strip} in a model should be valid" do
|
|
580
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
it "#{email.strip} should be valid using EmailValidator.valid?" do
|
|
584
|
+
expect(described_class).to be_valid(email)
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
it "#{email.strip} should not be invalid using EmailValidator.invalid?" do
|
|
588
|
+
expect(described_class).not_to be_invalid(email)
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
it "#{email.strip} should match the regexp" do
|
|
592
|
+
expect(!!(email =~ described_class.regexp)).to be(true)
|
|
593
|
+
end
|
|
146
594
|
end
|
|
147
595
|
|
|
148
|
-
|
|
149
|
-
|
|
596
|
+
context 'when in `:strict` mode' do
|
|
597
|
+
it "#{email.strip} in a model should be valid" do
|
|
598
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
it "#{email.strip} should not be valid using EmailValidator.valid?" do
|
|
602
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
it "#{email.strip} should be invalid using EmailValidator.invalid?" do
|
|
606
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
it "#{email.strip} should not match the regexp" do
|
|
610
|
+
expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
611
|
+
end
|
|
150
612
|
end
|
|
151
613
|
|
|
614
|
+
context 'when in `:rfc` mode' do
|
|
615
|
+
it "#{email.strip} in a model should not be valid" do
|
|
616
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
it "#{email.strip} should not be valid using EmailValidator.valid?" do
|
|
620
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
it "#{email.strip} should be invalid using EmailValidator.invalid?" do
|
|
624
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
it "#{email.strip} should not match the regexp" do
|
|
628
|
+
expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
629
|
+
end
|
|
630
|
+
end
|
|
631
|
+
end
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
context 'when `require_fqdn` is explicitly disabled' do
|
|
635
|
+
let(:opts) { { :require_fqdn => false } }
|
|
636
|
+
|
|
637
|
+
context 'when given a valid hostname-only email' do
|
|
638
|
+
let(:email) { 'someuser@somehost' }
|
|
639
|
+
|
|
640
|
+
context 'when using defaults' do
|
|
641
|
+
it 'is valid using EmailValidator.valid?' do
|
|
642
|
+
expect(described_class).to be_valid(email, opts)
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
646
|
+
expect(described_class).not_to be_invalid(email, opts)
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
it 'matches the regexp' do
|
|
650
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
context 'when in `:strict` mode' do
|
|
655
|
+
let(:opts) { { :require_fqdn => false, :mode => :strict } }
|
|
656
|
+
|
|
657
|
+
it 'is valid' do
|
|
658
|
+
expect(NonFqdnStrictUser.new(:email => email)).to be_valid
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
it 'is valid using EmailValidator.valid?' do
|
|
662
|
+
expect(described_class).to be_valid(email, opts)
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
666
|
+
expect(described_class).not_to be_invalid(email, opts)
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
it 'matches the regexp' do
|
|
670
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
671
|
+
end
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
context 'when in `:rfc` mode' do
|
|
675
|
+
let(:opts) { { :require_fqdn => false, :mode => :rfc } }
|
|
676
|
+
|
|
677
|
+
it 'is valid' do
|
|
678
|
+
expect(NonFqdnRfcUser.new(:email => email)).to be_valid
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
it 'is valid using EmailValidator.valid?' do
|
|
682
|
+
expect(described_class).to be_valid(email, opts)
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
686
|
+
expect(described_class).not_to be_invalid(email, opts)
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
it 'matches the regexp' do
|
|
690
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
691
|
+
end
|
|
692
|
+
end
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
context 'when given a valid email using an FQDN' do
|
|
696
|
+
let(:email) { 'someuser@somehost.somedomain' }
|
|
697
|
+
|
|
698
|
+
it 'is valid' do
|
|
699
|
+
expect(NonFqdnStrictUser.new(:email => email)).to be_valid
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
# rubocop:disable RSpec/PredicateMatcher
|
|
703
|
+
it 'is valid using EmailValidator.valid?' do
|
|
704
|
+
expect(described_class.valid?(email, opts)).to be(true)
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
708
|
+
expect(described_class.invalid?(email, opts)).to be(false)
|
|
709
|
+
end
|
|
710
|
+
# rubocop:enable RSpec/PredicateMatcher
|
|
711
|
+
|
|
712
|
+
it 'matches the regexp' do
|
|
713
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
context 'when in `:rfc` mode' do
|
|
717
|
+
let(:opts) { { :require_fqdn => false, :mode => :rfc } }
|
|
718
|
+
|
|
719
|
+
# rubocop:disable RSpec/PredicateMatcher
|
|
720
|
+
it 'is valid using EmailValidator.valid?' do
|
|
721
|
+
expect(described_class.valid?(email, opts)).to be(true)
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
725
|
+
expect(described_class.invalid?(email, opts)).to be(false)
|
|
726
|
+
end
|
|
727
|
+
# rubocop:enable RSpec/PredicateMatcher
|
|
728
|
+
|
|
729
|
+
it 'is valid' do
|
|
730
|
+
expect(NonFqdnRfcUser.new(:email => email)).to be_valid
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
it 'matches the regexp' do
|
|
734
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
735
|
+
end
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
context 'when requiring a non-matching domain' do
|
|
739
|
+
let(:domain) { 'example.com' }
|
|
740
|
+
let(:opts) { { :domain => domain } }
|
|
741
|
+
|
|
742
|
+
it 'is not valid' do
|
|
743
|
+
expect(DomainStrictUser.new(:email => email)).not_to be_valid
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
it 'is not valid using EmailValidator.valid?' do
|
|
747
|
+
expect(described_class).not_to be_valid(email, opts)
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
751
|
+
expect(described_class).to be_invalid(email, opts)
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
it 'does not matches the regexp' do
|
|
755
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(false)
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
context 'when in `:rfc` mode' do
|
|
759
|
+
let(:opts) { { :domain => domain, :require_fqdn => false, :mode => :rfc } }
|
|
760
|
+
|
|
761
|
+
it 'is not valid using EmailValidator.valid?' do
|
|
762
|
+
expect(described_class).not_to be_valid(email, opts)
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
766
|
+
expect(described_class).to be_invalid(email, opts)
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
it 'is not valid' do
|
|
770
|
+
expect(DomainRfcUser.new(:email => email)).not_to be_valid
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
it 'does not match the regexp' do
|
|
774
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(false)
|
|
775
|
+
end
|
|
776
|
+
end
|
|
777
|
+
end
|
|
152
778
|
end
|
|
153
779
|
end
|
|
154
780
|
end
|
|
781
|
+
# rubocop:enable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain
|
|
782
|
+
|
|
783
|
+
describe 'error messages' do
|
|
784
|
+
context 'when the message is not defined' do
|
|
785
|
+
let(:model) { DefaultUser.new :email => 'invalidemail@' }
|
|
155
786
|
|
|
156
|
-
|
|
157
|
-
context "when the message is not defined" do
|
|
158
|
-
subject { TestUser.new :email => 'invalidemail@' }
|
|
159
|
-
before { subject.valid? }
|
|
787
|
+
before { model.valid? }
|
|
160
788
|
|
|
161
|
-
it
|
|
162
|
-
expect(
|
|
789
|
+
it 'adds the default message' do
|
|
790
|
+
expect(model.errors[:email]).to include 'is invalid'
|
|
163
791
|
end
|
|
164
792
|
end
|
|
165
793
|
|
|
166
|
-
context
|
|
167
|
-
|
|
168
|
-
before { subject.valid? }
|
|
794
|
+
context 'when the message is defined' do
|
|
795
|
+
let(:model) { DefaultUserWithMessage.new :email_address => 'invalidemail@' }
|
|
169
796
|
|
|
170
|
-
|
|
171
|
-
|
|
797
|
+
before { model.valid? }
|
|
798
|
+
|
|
799
|
+
it 'adds the customized message' do
|
|
800
|
+
expect(model.errors[:email_address]).to include 'is not looking very good!'
|
|
172
801
|
end
|
|
173
802
|
end
|
|
174
803
|
end
|
|
175
804
|
|
|
176
|
-
describe
|
|
177
|
-
it
|
|
178
|
-
expect(
|
|
805
|
+
describe 'nil email' do
|
|
806
|
+
it 'is not valid when :allow_nil option is missing' do
|
|
807
|
+
expect(DefaultUser.new(:email => nil)).not_to be_valid
|
|
179
808
|
end
|
|
180
809
|
|
|
181
|
-
it
|
|
182
|
-
expect(
|
|
810
|
+
it 'is valid when :allow_nil options is set to true' do
|
|
811
|
+
expect(AllowNilDefaultUser.new(:email => nil)).to be_valid
|
|
183
812
|
end
|
|
184
813
|
|
|
185
|
-
it
|
|
186
|
-
expect(
|
|
814
|
+
it 'is not valid when :allow_nil option is set to false' do
|
|
815
|
+
expect(DisallowNilDefaultUser.new(:email => nil)).not_to be_valid
|
|
187
816
|
end
|
|
188
817
|
end
|
|
189
818
|
|
|
190
|
-
describe
|
|
191
|
-
context
|
|
819
|
+
describe 'limited to a domain' do
|
|
820
|
+
context 'when in `:strict` mode' do
|
|
821
|
+
it 'is not valid with mismatched domain' do
|
|
822
|
+
expect(DomainStrictUser.new(:email => 'user@not-matching.io')).not_to be_valid
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
it 'is valid with matching domain' do
|
|
826
|
+
expect(DomainStrictUser.new(:email => 'user@example.com')).to be_valid
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
it 'does not interpret the dot as any character' do
|
|
830
|
+
expect(DomainStrictUser.new(:email => 'user@example-com')).not_to be_valid
|
|
831
|
+
end
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
context 'when in `:rfc` mode' do
|
|
835
|
+
it 'does not interpret the dot as any character' do
|
|
836
|
+
expect(DomainRfcUser.new(:email => 'user@example-com')).not_to be_valid
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
it 'is valid with matching domain' do
|
|
840
|
+
expect(DomainRfcUser.new(:email => 'user@example.com')).to be_valid
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
it 'is not valid with mismatched domain' do
|
|
844
|
+
expect(DomainRfcUser.new(:email => 'user@not-matching.io')).not_to be_valid
|
|
845
|
+
end
|
|
846
|
+
end
|
|
847
|
+
end
|
|
848
|
+
|
|
849
|
+
describe 'default_options' do
|
|
850
|
+
let(:valid_email) { 'valid-email@localhost.localdomain' }
|
|
851
|
+
let(:invalid_email) { 'invalid email@localhost.localdomain' }
|
|
852
|
+
|
|
853
|
+
it 'validates valid using `:loose` mode' do
|
|
854
|
+
expect(DefaultUser.new(:email => valid_email)).to be_valid
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
it 'invalidates invalid using `:loose` mode' do
|
|
858
|
+
expect(DefaultUser.new(:email => invalid_email)).to be_invalid
|
|
859
|
+
end
|
|
860
|
+
|
|
861
|
+
context 'when `email_validator/strict` has been required' do
|
|
192
862
|
before { require 'email_validator/strict' }
|
|
193
863
|
|
|
194
|
-
it
|
|
195
|
-
expect(
|
|
864
|
+
it 'validates valid using `:strict` mode' do
|
|
865
|
+
expect(DefaultUser.new(:email => valid_email)).to be_valid
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
it 'invalidates invalid using `:strict` mode' do
|
|
869
|
+
expect(DefaultUser.new(:email => invalid_email)).to be_invalid
|
|
870
|
+
end
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
context 'when `email_validator/rfc` has been required' do
|
|
874
|
+
before { require 'email_validator/rfc' }
|
|
875
|
+
|
|
876
|
+
it 'validates valid using `:rfc` mode' do
|
|
877
|
+
expect(DefaultUser.new(:email => valid_email)).to be_valid
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
it 'invalidates invalid using `:rfc` mode' do
|
|
881
|
+
expect(DefaultUser.new(:email => invalid_email)).to be_invalid
|
|
196
882
|
end
|
|
197
883
|
end
|
|
198
884
|
end
|