email_validator 1.6.0 → 2.2.4
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 +131 -0
- data/README.md +172 -18
- data/lib/email_validator/rfc.rb +4 -0
- data/lib/email_validator/strict.rb +2 -3
- data/lib/email_validator.rb +152 -16
- data/spec/email_validator_spec.rb +1041 -116
- data/spec/spec_helper.rb +12 -2
- metadata +17 -45
- data/.document +0 -5
- data/.gitignore +0 -22
- data/.travis.yml +0 -7
- data/Changes.md +0 -11
- data/Gemfile +0 -3
- data/Rakefile +0 -10
- data/email_validator.gemspec +0 -23
|
@@ -1,201 +1,1126 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
|
-
class
|
|
3
|
+
class DefaultUser < TestModel
|
|
5
4
|
validates :email, :email => true
|
|
6
5
|
end
|
|
7
6
|
|
|
8
7
|
class StrictUser < TestModel
|
|
9
|
-
validates :email, :email => {:
|
|
8
|
+
validates :email, :email => { :mode => :strict }
|
|
10
9
|
end
|
|
11
10
|
|
|
12
|
-
class
|
|
13
|
-
validates :email, :email => {:
|
|
11
|
+
class RfcUser < TestModel
|
|
12
|
+
validates :email, :email => { :mode => :rfc }
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
class
|
|
17
|
-
validates :email, :email => {:allow_nil =>
|
|
15
|
+
class AllowNilDefaultUser < TestModel
|
|
16
|
+
validates :email, :email => { :allow_nil => true }
|
|
18
17
|
end
|
|
19
18
|
|
|
20
|
-
class
|
|
21
|
-
validates :
|
|
19
|
+
class AllowNilStrictUser < TestModel
|
|
20
|
+
validates :email, :email => { :allow_nil => true, :mode => :strict }
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
class AllowNilRfcUser < TestModel
|
|
24
|
+
validates :email, :email => { :allow_nil => true, :mode => :rfc }
|
|
25
|
+
end
|
|
26
|
+
|
|
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
|
|
42
|
+
|
|
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 RequireFqdnWithEmptyDomainUser < TestModel
|
|
56
|
+
validates :email_address, :email => { :require_fqdn => true, :domain => '' }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class RequireEmptyDomainStrictUser < TestModel
|
|
60
|
+
validates :email_address, :email => { :require_fqdn => true, :domain => '', :mode => :strict }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class RequireEmptyDomainRfcUser < TestModel
|
|
64
|
+
validates :email_address, :email => { :require_fqdn => true, :domain => '', :mode => :rfc }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class DefaultUserWithMessage < TestModel
|
|
68
|
+
validates :email_address, :email => { :message => 'is not looking very good!' }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
RSpec.describe EmailValidator do
|
|
72
|
+
describe 'validation' do
|
|
73
|
+
valid_special_chars = {
|
|
74
|
+
:ampersand => '&',
|
|
75
|
+
:asterisk => '*',
|
|
76
|
+
:backtick => '`',
|
|
77
|
+
:braceleft => '{',
|
|
78
|
+
:braceright => '}',
|
|
79
|
+
:caret => '^',
|
|
80
|
+
:dollar => '$',
|
|
81
|
+
:equals => '=',
|
|
82
|
+
:exclaim => '!',
|
|
83
|
+
:hash => '#',
|
|
84
|
+
:hyphen => '-',
|
|
85
|
+
:percent => '%',
|
|
86
|
+
:plus => '+',
|
|
87
|
+
:pipe => '|',
|
|
88
|
+
:question => '?',
|
|
89
|
+
:quotedouble => '"',
|
|
90
|
+
:quotesingle => "'",
|
|
91
|
+
:slash => '/',
|
|
92
|
+
:tilde => '~',
|
|
93
|
+
:underscore => '_'
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
invalid_special_chars = {
|
|
97
|
+
:backslash => '\\',
|
|
98
|
+
:braketleft => '[',
|
|
99
|
+
:braketright => ']',
|
|
100
|
+
:colon => ':',
|
|
101
|
+
:comma => ',',
|
|
102
|
+
:greater => '>',
|
|
103
|
+
:lesser => '<',
|
|
104
|
+
:parenleft => '(',
|
|
105
|
+
:parenright => ')',
|
|
106
|
+
:semicolon => ';'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
valid_includable = valid_special_chars.merge({ :dot => '.' })
|
|
110
|
+
valid_beginable = valid_special_chars
|
|
111
|
+
valid_endable = valid_special_chars
|
|
112
|
+
invalid_includable = { :at => '@' }
|
|
113
|
+
whitespace = { :newline => "\n", :tab => "\t", :carriage_return => "\r", :space => ' ' }
|
|
114
|
+
strictly_invalid_includable = invalid_special_chars
|
|
115
|
+
strictly_invalid_beginable = strictly_invalid_includable.merge({ :dot => '.' })
|
|
116
|
+
strictly_invalid_endable = strictly_invalid_beginable
|
|
117
|
+
domain_invalid_beginable = invalid_special_chars.merge(valid_special_chars)
|
|
118
|
+
domain_invalid_endable = domain_invalid_beginable
|
|
119
|
+
domain_invalid_includable = domain_invalid_beginable.reject { |k, _v| k == :hyphen }
|
|
120
|
+
|
|
121
|
+
# rubocop:disable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain
|
|
122
|
+
context 'when given the valid email' do
|
|
123
|
+
valid_includable.map { |k, v| [
|
|
124
|
+
"include-#{v}-#{k}@valid-characters-in-local.dev"
|
|
125
|
+
]}.concat(valid_beginable.map { |k, v| [
|
|
126
|
+
"#{v}start-with-#{k}@valid-characters-in-local.dev"
|
|
127
|
+
]}).concat(valid_endable.map { |k, v| [
|
|
128
|
+
"end-with-#{k}-#{v}@valid-characters-in-local.dev"
|
|
129
|
+
]}).concat([
|
|
130
|
+
'a+b@plus-in-local.com',
|
|
131
|
+
'a_b@underscore-in-local.com',
|
|
132
|
+
'user@example.com',
|
|
133
|
+
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@letters-in-local.dev',
|
|
134
|
+
'01234567890@numbers-in-local.dev',
|
|
135
|
+
'a@single-character-in-local.dev',
|
|
136
|
+
'one-character-third-level@a.example.com',
|
|
137
|
+
'single-character-in-sld@x.dev',
|
|
138
|
+
'local@dash-in-sld.com',
|
|
139
|
+
'numbers-in-sld@s123.com',
|
|
140
|
+
'one-letter-sld@x.dev',
|
|
141
|
+
'uncommon-tld@sld.museum',
|
|
142
|
+
'uncommon-tld@sld.travel',
|
|
143
|
+
'uncommon-tld@sld.mobi',
|
|
144
|
+
'country-code-tld@sld.uk',
|
|
145
|
+
'country-code-tld@sld.rw',
|
|
146
|
+
'local@sld.newTLD',
|
|
147
|
+
'local@sub.domains.com',
|
|
148
|
+
'aaa@bbb.co.jp',
|
|
149
|
+
'nigel.worthington@big.co.uk',
|
|
150
|
+
'f@c.com',
|
|
151
|
+
'f@s.c',
|
|
152
|
+
'someuser@somehost.somedomain',
|
|
153
|
+
'mixed-1234-in-{+^}-local@sld.dev',
|
|
154
|
+
'partially."quoted"@sld.com',
|
|
155
|
+
'areallylongnameaasdfasdfasdfasdf@asdfasdfasdfasdfasdf.ab.cd.ef.gh.co.ca',
|
|
156
|
+
'john.doe@2020.example.com',
|
|
157
|
+
'john.doe@2a.com',
|
|
158
|
+
'john.doe@a2.com',
|
|
159
|
+
'john.doe@2020.a-z.com',
|
|
160
|
+
'john.doe@2020.a2z.com',
|
|
161
|
+
'john.doe@2020.12345a6789.com',
|
|
162
|
+
'jonh.doe@163.com',
|
|
163
|
+
'test@umläut.com', # non-ASCII
|
|
164
|
+
'test@xn--umlut-ira.com' # ASCII-compatibale encoding of non-ASCII
|
|
165
|
+
]).flatten.each do |email|
|
|
166
|
+
context 'when using defaults' do
|
|
167
|
+
it "'#{email}' should be valid" do
|
|
168
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
172
|
+
expect(described_class).to be_valid(email)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
176
|
+
expect(described_class).not_to be_invalid(email)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "'#{email}' should match the regexp" do
|
|
180
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
context 'when in `:strict` mode' do
|
|
185
|
+
it "'#{email}' should be valid" do
|
|
186
|
+
expect(StrictUser.new(:email => email)).to be_valid
|
|
187
|
+
end
|
|
25
188
|
|
|
26
|
-
|
|
27
|
-
|
|
189
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
190
|
+
expect(described_class).to be_valid(email, :mode => :strict)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "'#{email}' should not be invalid using EmailValidator.valid?" do
|
|
194
|
+
expect(described_class).not_to be_invalid(email, :mode => :strict)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "'#{email}' should match the regexp" do
|
|
198
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true)
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
context 'when in `:rfc` mode' do
|
|
203
|
+
it "'#{email}' should be valid" do
|
|
204
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
208
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
212
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "'#{email}' should match the regexp" do
|
|
216
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
context 'when given the valid host-only email' do
|
|
28
223
|
[
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
" user@example.com ",
|
|
33
|
-
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@letters-in-local.org",
|
|
34
|
-
"01234567890@numbers-in-local.net",
|
|
35
|
-
"a@single-character-in-local.org",
|
|
36
|
-
"one-character-third-level@a.example.com",
|
|
37
|
-
"single-character-in-sld@x.org",
|
|
38
|
-
"local@dash-in-sld.com",
|
|
39
|
-
"letters-in-sld@123.com",
|
|
40
|
-
"one-letter-sld@x.org",
|
|
41
|
-
"uncommon-tld@sld.museum",
|
|
42
|
-
"uncommon-tld@sld.travel",
|
|
43
|
-
"uncommon-tld@sld.mobi",
|
|
44
|
-
"country-code-tld@sld.uk",
|
|
45
|
-
"country-code-tld@sld.rw",
|
|
46
|
-
"local@sld.newTLD",
|
|
47
|
-
"local@sub.domains.com",
|
|
48
|
-
"aaa@bbb.co.jp",
|
|
49
|
-
"nigel.worthington@big.co.uk",
|
|
50
|
-
"f@c.com",
|
|
51
|
-
"areallylongnameaasdfasdfasdfasdf@asdfasdfasdfasdfasdf.ab.cd.ef.gh.co.ca",
|
|
52
|
-
"ящик@яндекс.рф"
|
|
224
|
+
'f@s',
|
|
225
|
+
'user@localhost',
|
|
226
|
+
'someuser@somehost'
|
|
53
227
|
].each do |email|
|
|
228
|
+
context 'when using defaults' do
|
|
229
|
+
it "'#{email}' should be valid" do
|
|
230
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
234
|
+
expect(described_class).to be_valid(email)
|
|
235
|
+
end
|
|
54
236
|
|
|
55
|
-
|
|
56
|
-
|
|
237
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
238
|
+
expect(described_class).not_to be_invalid(email)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it "'#{email}' should match the regexp" do
|
|
242
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
243
|
+
end
|
|
57
244
|
end
|
|
58
245
|
|
|
59
|
-
|
|
60
|
-
|
|
246
|
+
context 'when in `:strict` mode' do
|
|
247
|
+
it "'#{email}' should not be valid" do
|
|
248
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
252
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
256
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it "'#{email}' should not match the regexp" do
|
|
260
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
261
|
+
end
|
|
61
262
|
end
|
|
62
263
|
|
|
63
|
-
|
|
64
|
-
|
|
264
|
+
context 'when in `:rfc` mode' do
|
|
265
|
+
it "'#{email}' should be valid" do
|
|
266
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
270
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
274
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "'#{email}' should match the regexp" do
|
|
278
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
279
|
+
end
|
|
65
280
|
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
context 'when given the numeric domain' do
|
|
285
|
+
[
|
|
286
|
+
'only-numbers-in-domain-label@sub.123.custom'
|
|
287
|
+
].each do |email|
|
|
288
|
+
context 'when using defaults' do
|
|
289
|
+
it "'#{email}' should be valid" do
|
|
290
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
291
|
+
end
|
|
66
292
|
|
|
67
|
-
|
|
68
|
-
|
|
293
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
294
|
+
expect(described_class).to be_valid(email)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
298
|
+
expect(described_class).not_to be_invalid(email)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it "'#{email}' should match the regexp" do
|
|
302
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
303
|
+
end
|
|
69
304
|
end
|
|
70
305
|
|
|
71
|
-
|
|
72
|
-
|
|
306
|
+
context 'when in `:strict` mode' do
|
|
307
|
+
it "'#{email}' should be valid" do
|
|
308
|
+
expect(StrictUser.new(:email => email)).to be_valid
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
312
|
+
expect(described_class).to be_valid(email, :mode => :strict)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "'#{email}' should be not invalid using EmailValidator.invalid?" do
|
|
316
|
+
expect(described_class).not_to be_invalid(email, :mode => :strict)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
it "'#{email}' should match the regexp" do
|
|
320
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true)
|
|
321
|
+
end
|
|
73
322
|
end
|
|
74
323
|
|
|
324
|
+
context 'when in `:rfc` mode' do
|
|
325
|
+
it "'#{email}' should be valid" do
|
|
326
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
330
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
334
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
it "'#{email}' should match the regexp" do
|
|
338
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
75
341
|
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
context 'when given the valid mailbox-only email' do
|
|
345
|
+
valid_includable.map { |k, v| [
|
|
346
|
+
"user-#{v}-#{k}-name"
|
|
347
|
+
]}.concat(valid_beginable.map { |k, v| [
|
|
348
|
+
"#{v}-start-with-#{k}-user"
|
|
349
|
+
]}).concat(valid_endable.map { |k, v| [
|
|
350
|
+
"end-with-#{k}-#{v}"
|
|
351
|
+
]}).concat([
|
|
352
|
+
'user'
|
|
353
|
+
]).flatten.each do |email|
|
|
354
|
+
context 'when using defaults' do
|
|
355
|
+
it "'#{email}' should not be valid" do
|
|
356
|
+
expect(DefaultUser.new(:email => email)).not_to be_valid
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
360
|
+
expect(described_class).not_to be_valid(email)
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
364
|
+
expect(described_class).to be_invalid(email)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
it "'#{email}' should not match the regexp" do
|
|
368
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(false)
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
context 'when in `:strict` mode' do
|
|
373
|
+
it "'#{email}' should not be valid" do
|
|
374
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
378
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
382
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it "'#{email}' should not match the regexp" do
|
|
386
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
context 'when in `:rfc` mode' do
|
|
391
|
+
it "'#{email}' should be valid" do
|
|
392
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
396
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
400
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
401
|
+
end
|
|
76
402
|
|
|
403
|
+
it "'#{email}' should match the regexp" do
|
|
404
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
end
|
|
77
408
|
end
|
|
78
409
|
|
|
79
|
-
context
|
|
410
|
+
context 'when given the valid IP address email' do
|
|
80
411
|
[
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"f@s.c",
|
|
84
|
-
"@bar.com",
|
|
85
|
-
"test@example.com@example.com",
|
|
86
|
-
"test@",
|
|
87
|
-
"@missing-local.org",
|
|
88
|
-
"a b@space-in-local.com",
|
|
89
|
-
"! \#$%\`|@invalid-characters-in-local.org",
|
|
90
|
-
"<>@[]\`|@even-more-invalid-characters-in-local.org",
|
|
91
|
-
"missing-sld@.com",
|
|
92
|
-
"invalid-characters-in-sld@! \"\#$%(),/;<>_[]\`|.org",
|
|
93
|
-
"missing-dot-before-tld@com",
|
|
94
|
-
"missing-tld@sld.",
|
|
95
|
-
" ",
|
|
96
|
-
"missing-at-sign.net",
|
|
97
|
-
"unbracketed-IP@127.0.0.1",
|
|
98
|
-
"invalid-ip@127.0.0.1.26",
|
|
99
|
-
"another-invalid-ip@127.0.0.256",
|
|
100
|
-
"IP-and-port@127.0.0.1:25",
|
|
101
|
-
"the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.net",
|
|
102
|
-
"user@example.com\n<script>alert('hello')</script>"
|
|
412
|
+
'bracketed-IP@[127.0.0.1]',
|
|
413
|
+
'bracketed-and-labeled-IPv6@[IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678]'
|
|
103
414
|
].each do |email|
|
|
415
|
+
context 'when using defaults' do
|
|
416
|
+
it "'#{email}' should be valid" do
|
|
417
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
421
|
+
expect(described_class).to be_valid(email)
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
425
|
+
expect(described_class).not_to be_invalid(email)
|
|
426
|
+
end
|
|
104
427
|
|
|
105
|
-
|
|
106
|
-
|
|
428
|
+
it "'#{email}' should match the regexp" do
|
|
429
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
430
|
+
end
|
|
107
431
|
end
|
|
108
432
|
|
|
109
|
-
|
|
110
|
-
|
|
433
|
+
context 'when in `:strict` mode' do
|
|
434
|
+
it "'#{email}' should not be valid" do
|
|
435
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
439
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
443
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
it "'#{email}' should not match the regexp" do
|
|
447
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
448
|
+
end
|
|
111
449
|
end
|
|
112
450
|
|
|
113
|
-
|
|
114
|
-
|
|
451
|
+
context 'when in `:rfc` mode' do
|
|
452
|
+
it "'#{email}' should be valid" do
|
|
453
|
+
expect(RfcUser.new(:email => email)).to be_valid
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
457
|
+
expect(described_class).to be_valid(email, :mode => :rfc)
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
461
|
+
expect(described_class).not_to be_invalid(email, :mode => :rfc)
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
it "'#{email}' should match the regexp" do
|
|
465
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true)
|
|
466
|
+
end
|
|
115
467
|
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
116
470
|
|
|
117
|
-
|
|
118
|
-
|
|
471
|
+
context 'when given the invalid email' do
|
|
472
|
+
invalid_includable.map { |k, v| [
|
|
473
|
+
"include-#{v}-#{k}@invalid-characters-in-local.dev"
|
|
474
|
+
]}.concat(domain_invalid_beginable.map { |k, v| [
|
|
475
|
+
"start-with-#{k}@#{v}invalid-characters-in-domain.dev"
|
|
476
|
+
]}).concat(domain_invalid_endable.map { |k, v| [
|
|
477
|
+
"end-with-#{k}@invalid-characters-in-domain#{v}.dev"
|
|
478
|
+
]}).concat(domain_invalid_includable.map { |k, v| [
|
|
479
|
+
"include-#{k}@invalid-characters-#{v}-in-domain.dev"
|
|
480
|
+
]}).concat([
|
|
481
|
+
'test@example.com@example.com',
|
|
482
|
+
'missing-sld@.com',
|
|
483
|
+
'missing-tld@sld.',
|
|
484
|
+
'unbracketed-IPv6@abcd:ef01:1234:5678:9abc:def0:1234:5678',
|
|
485
|
+
'unbracketed-and-labled-IPv6@IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678',
|
|
486
|
+
'bracketed-and-unlabeled-IPv6@[abcd:ef01:1234:5678:9abc:def0:1234:5678]',
|
|
487
|
+
'unbracketed-IPv4@127.0.0.1',
|
|
488
|
+
'invalid-IPv4@127.0.0.1.26',
|
|
489
|
+
'another-invalid-IPv4@127.0.0.256',
|
|
490
|
+
'IPv4-and-port@127.0.0.1:25',
|
|
491
|
+
'host-beginning-with-dot@.example.com',
|
|
492
|
+
'domain-beginning-with-dash@-example.com',
|
|
493
|
+
'domain-ending-with-dash@example-.com',
|
|
494
|
+
'the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.dev',
|
|
495
|
+
"domain-too-long@t#{".#{'o' * 63}" * 5}.long",
|
|
496
|
+
"user@example.com<script>alert('hello')</script>"
|
|
497
|
+
]).flatten.each do |email|
|
|
498
|
+
context 'when using defaults' do
|
|
499
|
+
it "'#{email}' should be valid" do
|
|
500
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
|
504
|
+
expect(described_class).to be_valid(email)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
it "'#{email}' should not be invalid using EmailValidator.invalid?" do
|
|
508
|
+
expect(described_class).not_to be_invalid(email)
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it "'#{email}' should match the regexp" do
|
|
512
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(true)
|
|
513
|
+
end
|
|
119
514
|
end
|
|
120
515
|
|
|
121
|
-
|
|
122
|
-
|
|
516
|
+
context 'when in `:strict` mode' do
|
|
517
|
+
it "'#{email}' should not be valid" do
|
|
518
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
522
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
526
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
it "'#{email}' should not match the regexp" do
|
|
530
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
531
|
+
end
|
|
123
532
|
end
|
|
124
533
|
|
|
534
|
+
context 'when in `:rfc` mode' do
|
|
535
|
+
it "'#{email}' should not be valid" do
|
|
536
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
540
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
544
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
it "'#{email}' should not match the regexp" do
|
|
548
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
549
|
+
end
|
|
550
|
+
end
|
|
125
551
|
end
|
|
126
552
|
end
|
|
127
553
|
|
|
128
|
-
context
|
|
554
|
+
context 'when given the invalid email with whitespace in parts' do
|
|
555
|
+
whitespace.map { |k, v| [
|
|
556
|
+
"include-#{v}-#{k}@invalid-characters-in-local.dev"
|
|
557
|
+
]}.concat([
|
|
558
|
+
'foo @bar.com',
|
|
559
|
+
"foo\t@bar.com",
|
|
560
|
+
"foo\n@bar.com",
|
|
561
|
+
"foo\r@bar.com",
|
|
562
|
+
'test@ example.com',
|
|
563
|
+
'user@example .com',
|
|
564
|
+
"user@example\t.com",
|
|
565
|
+
"user@example\n.com",
|
|
566
|
+
"user@example\r.com",
|
|
567
|
+
'user@exam ple.com',
|
|
568
|
+
"user@exam\tple.com",
|
|
569
|
+
"user@exam\nple.com",
|
|
570
|
+
"user@exam\rple.com",
|
|
571
|
+
'us er@example.com',
|
|
572
|
+
"us\ter@example.com",
|
|
573
|
+
"us\ner@example.com",
|
|
574
|
+
"us\rer@example.com",
|
|
575
|
+
"user@example.com\n<script>alert('hello')</script>",
|
|
576
|
+
"user@example.com\t<script>alert('hello')</script>",
|
|
577
|
+
"user@example.com\r<script>alert('hello')</script>",
|
|
578
|
+
"user@example.com <script>alert('hello')</script>",
|
|
579
|
+
' leading-whitespace@example.com',
|
|
580
|
+
'trailing-whitespace@example.com ',
|
|
581
|
+
' leading-and-trailing-whitespace@example.com ',
|
|
582
|
+
' user-with-leading-whitespace-space@example.com',
|
|
583
|
+
"\tuser-with-leading-whitespace-tab@example.com",
|
|
584
|
+
"
|
|
585
|
+
user-with-leading-whitespace-newline@example.com",
|
|
586
|
+
'domain-with-trailing-whitespace-space@example.com ',
|
|
587
|
+
"domain-with-trailing-whitespace-tab@example.com\t",
|
|
588
|
+
"domain-with-trailing-whitespace-newline@example.com
|
|
589
|
+
"
|
|
590
|
+
]).flatten.each do |email|
|
|
591
|
+
context 'when using defaults' do
|
|
592
|
+
it "'#{email}' should not be valid" do
|
|
593
|
+
expect(DefaultUser.new(:email => email)).not_to be_valid
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
597
|
+
expect(described_class).not_to be_valid(email)
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
601
|
+
expect(described_class).to be_invalid(email)
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
it "'#{email}' should not match the regexp" do
|
|
605
|
+
expect(!!(email =~ described_class.regexp)).to be(false)
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
context 'when in `:strict` mode' do
|
|
610
|
+
it "'#{email}' should not be valid" do
|
|
611
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
615
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
619
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
it "'#{email}' should not match the regexp" do
|
|
623
|
+
expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
context 'when in `:rfc` mode' do
|
|
628
|
+
it "'#{email}' should not be valid" do
|
|
629
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
633
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
637
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
it "'#{email}' should not match the regexp" do
|
|
641
|
+
expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
context 'when given the invalid email with missing parts' do
|
|
129
648
|
[
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
"mixed-1234-in-{+^}-local@sld.net"
|
|
649
|
+
'',
|
|
650
|
+
'@bar.com',
|
|
651
|
+
'test@',
|
|
652
|
+
'@missing-local.dev',
|
|
653
|
+
' '
|
|
136
654
|
].each do |email|
|
|
655
|
+
context 'when using defaults' do
|
|
656
|
+
it "'#{email}' should not be valid" do
|
|
657
|
+
expect(DefaultUser.new(:email => email)).not_to be_valid
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
661
|
+
expect(described_class).not_to be_valid(email)
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
665
|
+
expect(described_class).to be_invalid(email)
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
it "'#{email}' should not match the regexp" do
|
|
669
|
+
expect(!!(email.strip =~ described_class.regexp)).to be(false)
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
context 'when in `:strict` mode' do
|
|
674
|
+
it "'#{email}' should not be valid" do
|
|
675
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
679
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
683
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
it "'#{email}' should not match the regexp" do
|
|
687
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
688
|
+
end
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
context 'when in `:rfc` mode' do
|
|
692
|
+
it "'#{email}' should not be valid" do
|
|
693
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
it "'#{email}' should not be valid using EmailValidator.valid?" do
|
|
697
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
|
701
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
it "'#{email}' should not match the regexp" do
|
|
705
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
706
|
+
end
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
context 'when given the strictly invalid email' do
|
|
712
|
+
strictly_invalid_includable.map { |k, v| [
|
|
713
|
+
"include-#{v}-#{k}@invalid-characters-in-local.dev"
|
|
714
|
+
]}.concat(strictly_invalid_beginable.map { |k, v| [
|
|
715
|
+
"#{v}start-with-#{k}@invalid-characters-in-local.dev"
|
|
716
|
+
]}).concat(strictly_invalid_endable.map { |k, v| [
|
|
717
|
+
"end-with-#{k}#{v}@invalid-characters-in-local.dev"
|
|
718
|
+
]}).concat([
|
|
719
|
+
'user..-with-double-dots@example.com',
|
|
720
|
+
'.user-beginning-with-dot@example.com',
|
|
721
|
+
'user-ending-with-dot.@example.com',
|
|
722
|
+
'fully-numeric-tld@example.123'
|
|
723
|
+
]).flatten.each do |email|
|
|
724
|
+
context 'when using defaults' do
|
|
725
|
+
it "#{email.strip} in a model should be valid" do
|
|
726
|
+
expect(DefaultUser.new(:email => email)).to be_valid
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
it "#{email.strip} should be valid using EmailValidator.valid?" do
|
|
730
|
+
expect(described_class).to be_valid(email)
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
it "#{email.strip} should not be invalid using EmailValidator.invalid?" do
|
|
734
|
+
expect(described_class).not_to be_invalid(email)
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
it "#{email.strip} should match the regexp" do
|
|
738
|
+
expect(!!(email =~ described_class.regexp)).to be(true)
|
|
739
|
+
end
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
context 'when in `:strict` mode' do
|
|
743
|
+
it "#{email.strip} in a model should not be valid" do
|
|
744
|
+
expect(StrictUser.new(:email => email)).not_to be_valid
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
it "#{email.strip} should not be valid using EmailValidator.valid?" do
|
|
748
|
+
expect(described_class).not_to be_valid(email, :mode => :strict)
|
|
749
|
+
end
|
|
750
|
+
|
|
751
|
+
it "#{email.strip} should be invalid using EmailValidator.invalid?" do
|
|
752
|
+
expect(described_class).to be_invalid(email, :mode => :strict)
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
it "#{email.strip} should not match the regexp" do
|
|
756
|
+
expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false)
|
|
757
|
+
end
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
context 'when in `:rfc` mode' do
|
|
761
|
+
it "#{email.strip} in a model should not be valid" do
|
|
762
|
+
expect(RfcUser.new(:email => email)).not_to be_valid
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
it "#{email.strip} should not be valid using EmailValidator.valid?" do
|
|
766
|
+
expect(described_class).not_to be_valid(email, :mode => :rfc)
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
it "#{email.strip} should be invalid using EmailValidator.invalid?" do
|
|
770
|
+
expect(described_class).to be_invalid(email, :mode => :rfc)
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
it "#{email.strip} should not match the regexp" do
|
|
774
|
+
expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false)
|
|
775
|
+
end
|
|
776
|
+
end
|
|
777
|
+
end
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
context 'when `require_fqdn` is explicitly enabled with a blank domain' do
|
|
781
|
+
let(:opts) { { :require_fqdn => true, :domain => '' } }
|
|
782
|
+
|
|
783
|
+
context 'when given a email containing any domain' do
|
|
784
|
+
let(:email) { 'someuser@somehost' }
|
|
785
|
+
|
|
786
|
+
context 'when using defaults' do
|
|
787
|
+
it 'is not valid in a model' do
|
|
788
|
+
expect(RequireFqdnWithEmptyDomainUser.new(:email => email)).not_to be_valid
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
it 'is not using EmailValidator.valid?' do
|
|
792
|
+
expect(described_class).not_to be_valid(email, opts)
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
796
|
+
expect(described_class).to be_invalid(email, opts)
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
it 'does not match the regexp' do
|
|
800
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(false)
|
|
801
|
+
end
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
context 'when in `:strict` mode' do
|
|
805
|
+
it 'is not valid in a model' do
|
|
806
|
+
expect(RequireEmptyDomainStrictUser.new(:email => email)).not_to be_valid
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
it 'is not using EmailValidator.valid?' do
|
|
810
|
+
expect(described_class).not_to be_valid(email, opts.merge({ :mode => :strict }))
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
814
|
+
expect(described_class).to be_invalid(email, opts.merge({ :mode => :strict }))
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
it 'does not match the regexp' do
|
|
818
|
+
expect(!!(email =~ described_class.regexp(opts.merge({ :mode => :strict })))).to be(false)
|
|
819
|
+
end
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
context 'when in `:rfc` mode' do
|
|
823
|
+
it 'is not valid in a model' do
|
|
824
|
+
expect(RequireEmptyDomainRfcUser.new(:email => email)).not_to be_valid
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
it 'is not using EmailValidator.valid?' do
|
|
828
|
+
expect(described_class).not_to be_valid(email, opts.merge({ :mode => :rfc }))
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
832
|
+
expect(described_class).to be_invalid(email, opts.merge({ :mode => :rfc }))
|
|
833
|
+
end
|
|
834
|
+
|
|
835
|
+
it 'does not match the regexp' do
|
|
836
|
+
expect(!!(email =~ described_class.regexp(opts.merge({ :mode => :rfc })))).to be(false)
|
|
837
|
+
end
|
|
838
|
+
end
|
|
839
|
+
end
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
context 'when `require_fqdn` is explicitly disabled' do
|
|
843
|
+
let(:opts) { { :require_fqdn => false } }
|
|
844
|
+
|
|
845
|
+
context 'when given a valid hostname-only email' do
|
|
846
|
+
let(:email) { 'someuser@somehost' }
|
|
847
|
+
|
|
848
|
+
context 'when using defaults' do
|
|
849
|
+
it 'is valid using EmailValidator.valid?' do
|
|
850
|
+
expect(described_class).to be_valid(email, opts)
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
854
|
+
expect(described_class).not_to be_invalid(email, opts)
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
it 'matches the regexp' do
|
|
858
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
859
|
+
end
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
# Strict mode enables `require_fqdn` anyway
|
|
863
|
+
context 'when in `:strict` mode' do
|
|
864
|
+
let(:opts) { { :require_fqdn => false, :mode => :strict } }
|
|
865
|
+
|
|
866
|
+
it 'is not valid' do
|
|
867
|
+
expect(NonFqdnStrictUser.new(:email => email)).not_to be_valid
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
it 'is not valid using EmailValidator.valid?' do
|
|
871
|
+
expect(described_class).not_to be_valid(email, opts)
|
|
872
|
+
end
|
|
873
|
+
|
|
874
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
875
|
+
expect(described_class).to be_invalid(email, opts)
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
it 'matches the regexp' do
|
|
879
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(false)
|
|
880
|
+
end
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
context 'when in `:rfc` mode' do
|
|
884
|
+
let(:opts) { { :require_fqdn => false, :mode => :rfc } }
|
|
885
|
+
|
|
886
|
+
it 'is valid' do
|
|
887
|
+
expect(NonFqdnRfcUser.new(:email => email)).to be_valid
|
|
888
|
+
end
|
|
889
|
+
|
|
890
|
+
it 'is valid using EmailValidator.valid?' do
|
|
891
|
+
expect(described_class).to be_valid(email, opts)
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
895
|
+
expect(described_class).not_to be_invalid(email, opts)
|
|
896
|
+
end
|
|
897
|
+
|
|
898
|
+
it 'matches the regexp' do
|
|
899
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
900
|
+
end
|
|
901
|
+
end
|
|
902
|
+
end
|
|
137
903
|
|
|
138
|
-
|
|
139
|
-
|
|
904
|
+
context 'when given a valid email using an FQDN' do
|
|
905
|
+
let(:email) { 'someuser@somehost.somedomain' }
|
|
906
|
+
|
|
907
|
+
it 'is valid' do
|
|
908
|
+
expect(NonFqdnStrictUser.new(:email => email)).to be_valid
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
# rubocop:disable RSpec/PredicateMatcher
|
|
912
|
+
it 'is valid using EmailValidator.valid?' do
|
|
913
|
+
expect(described_class.valid?(email, opts)).to be(true)
|
|
140
914
|
end
|
|
141
915
|
|
|
142
|
-
it
|
|
143
|
-
expect(
|
|
916
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
917
|
+
expect(described_class.invalid?(email, opts)).to be(false)
|
|
144
918
|
end
|
|
919
|
+
# rubocop:enable RSpec/PredicateMatcher
|
|
145
920
|
|
|
146
|
-
it
|
|
147
|
-
expect(email =~
|
|
921
|
+
it 'matches the regexp' do
|
|
922
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
148
923
|
end
|
|
149
924
|
|
|
150
|
-
|
|
151
|
-
|
|
925
|
+
context 'when in `:rfc` mode' do
|
|
926
|
+
let(:opts) { { :require_fqdn => false, :mode => :rfc } }
|
|
927
|
+
|
|
928
|
+
# rubocop:disable RSpec/PredicateMatcher
|
|
929
|
+
it 'is valid using EmailValidator.valid?' do
|
|
930
|
+
expect(described_class.valid?(email, opts)).to be(true)
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
it 'is not invalid using EmailValidator.invalid?' do
|
|
934
|
+
expect(described_class.invalid?(email, opts)).to be(false)
|
|
935
|
+
end
|
|
936
|
+
# rubocop:enable RSpec/PredicateMatcher
|
|
937
|
+
|
|
938
|
+
it 'is valid' do
|
|
939
|
+
expect(NonFqdnRfcUser.new(:email => email)).to be_valid
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
it 'matches the regexp' do
|
|
943
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(true)
|
|
944
|
+
end
|
|
152
945
|
end
|
|
153
946
|
|
|
947
|
+
context 'when requiring a non-matching domain' do
|
|
948
|
+
let(:domain) { 'example.com' }
|
|
949
|
+
let(:opts) { { :domain => domain } }
|
|
950
|
+
|
|
951
|
+
it 'is not valid' do
|
|
952
|
+
expect(DomainStrictUser.new(:email => email)).not_to be_valid
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
it 'is not valid using EmailValidator.valid?' do
|
|
956
|
+
expect(described_class).not_to be_valid(email, opts)
|
|
957
|
+
end
|
|
958
|
+
|
|
959
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
960
|
+
expect(described_class).to be_invalid(email, opts)
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
it 'does not matches the regexp' do
|
|
964
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(false)
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
context 'when in `:rfc` mode' do
|
|
968
|
+
let(:opts) { { :domain => domain, :require_fqdn => false, :mode => :rfc } }
|
|
969
|
+
|
|
970
|
+
it 'is not valid using EmailValidator.valid?' do
|
|
971
|
+
expect(described_class).not_to be_valid(email, opts)
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
it 'is invalid using EmailValidator.invalid?' do
|
|
975
|
+
expect(described_class).to be_invalid(email, opts)
|
|
976
|
+
end
|
|
977
|
+
|
|
978
|
+
it 'is not valid' do
|
|
979
|
+
expect(DomainRfcUser.new(:email => email)).not_to be_valid
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
it 'does not match the regexp' do
|
|
983
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(false)
|
|
984
|
+
end
|
|
985
|
+
end
|
|
986
|
+
end
|
|
154
987
|
end
|
|
155
988
|
end
|
|
156
989
|
end
|
|
990
|
+
# rubocop:enable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain
|
|
991
|
+
|
|
992
|
+
describe 'error messages' do
|
|
993
|
+
context 'when the message is not defined' do
|
|
994
|
+
let(:model) { DefaultUser.new :email => 'invalidemail@' }
|
|
157
995
|
|
|
158
|
-
|
|
159
|
-
context "when the message is not defined" do
|
|
160
|
-
subject { TestUser.new :email => 'invalidemail@' }
|
|
161
|
-
before { subject.valid? }
|
|
996
|
+
before { model.valid? }
|
|
162
997
|
|
|
163
|
-
it
|
|
164
|
-
expect(
|
|
998
|
+
it 'adds the default message' do
|
|
999
|
+
expect(model.errors[:email]).to include 'is invalid'
|
|
165
1000
|
end
|
|
166
1001
|
end
|
|
167
1002
|
|
|
168
|
-
context
|
|
169
|
-
|
|
170
|
-
before { subject.valid? }
|
|
1003
|
+
context 'when the message is defined' do
|
|
1004
|
+
let(:model) { DefaultUserWithMessage.new :email_address => 'invalidemail@' }
|
|
171
1005
|
|
|
172
|
-
|
|
173
|
-
|
|
1006
|
+
before { model.valid? }
|
|
1007
|
+
|
|
1008
|
+
it 'adds the customized message' do
|
|
1009
|
+
expect(model.errors[:email_address]).to include 'is not looking very good!'
|
|
174
1010
|
end
|
|
175
1011
|
end
|
|
176
1012
|
end
|
|
177
1013
|
|
|
178
|
-
describe
|
|
179
|
-
it
|
|
180
|
-
expect(
|
|
1014
|
+
describe 'nil email' do
|
|
1015
|
+
it 'is not valid when :allow_nil option is missing' do
|
|
1016
|
+
expect(DefaultUser.new(:email => nil)).not_to be_valid
|
|
181
1017
|
end
|
|
182
1018
|
|
|
183
|
-
it
|
|
184
|
-
expect(
|
|
1019
|
+
it 'is valid when :allow_nil options is set to true' do
|
|
1020
|
+
expect(AllowNilDefaultUser.new(:email => nil)).to be_valid
|
|
185
1021
|
end
|
|
186
1022
|
|
|
187
|
-
it
|
|
188
|
-
expect(
|
|
1023
|
+
it 'is not valid when :allow_nil option is set to false' do
|
|
1024
|
+
expect(DisallowNilDefaultUser.new(:email => nil)).not_to be_valid
|
|
189
1025
|
end
|
|
190
1026
|
end
|
|
191
1027
|
|
|
192
|
-
describe
|
|
193
|
-
context
|
|
1028
|
+
describe 'limited to a domain' do
|
|
1029
|
+
context 'when in `:strict` mode' do
|
|
1030
|
+
it 'is not valid with mismatched domain' do
|
|
1031
|
+
expect(DomainStrictUser.new(:email => 'user@not-matching.io')).not_to be_valid
|
|
1032
|
+
end
|
|
1033
|
+
|
|
1034
|
+
it 'is valid with matching domain' do
|
|
1035
|
+
expect(DomainStrictUser.new(:email => 'user@example.com')).to be_valid
|
|
1036
|
+
end
|
|
1037
|
+
|
|
1038
|
+
it 'does not interpret the dot as any character' do
|
|
1039
|
+
expect(DomainStrictUser.new(:email => 'user@example-com')).not_to be_valid
|
|
1040
|
+
end
|
|
1041
|
+
end
|
|
1042
|
+
|
|
1043
|
+
context 'when in `:rfc` mode' do
|
|
1044
|
+
it 'does not interpret the dot as any character' do
|
|
1045
|
+
expect(DomainRfcUser.new(:email => 'user@example-com')).not_to be_valid
|
|
1046
|
+
end
|
|
1047
|
+
|
|
1048
|
+
it 'is valid with matching domain' do
|
|
1049
|
+
expect(DomainRfcUser.new(:email => 'user@example.com')).to be_valid
|
|
1050
|
+
end
|
|
1051
|
+
|
|
1052
|
+
it 'is not valid with mismatched domain' do
|
|
1053
|
+
expect(DomainRfcUser.new(:email => 'user@not-matching.io')).not_to be_valid
|
|
1054
|
+
end
|
|
1055
|
+
end
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
describe 'default_options' do
|
|
1059
|
+
let(:valid_email) { 'valid-email@localhost.localdomain' }
|
|
1060
|
+
let(:invalid_email) { 'invalid email@localhost.localdomain' }
|
|
1061
|
+
|
|
1062
|
+
it 'validates valid using `:loose` mode' do
|
|
1063
|
+
expect(DefaultUser.new(:email => valid_email)).to be_valid
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
it 'invalidates invalid using `:loose` mode' do
|
|
1067
|
+
expect(DefaultUser.new(:email => invalid_email)).to be_invalid
|
|
1068
|
+
end
|
|
1069
|
+
|
|
1070
|
+
context 'when `email_validator/strict` has been required' do
|
|
194
1071
|
before { require 'email_validator/strict' }
|
|
195
1072
|
|
|
196
|
-
it
|
|
197
|
-
expect(
|
|
1073
|
+
it 'validates valid using `:strict` mode' do
|
|
1074
|
+
expect(DefaultUser.new(:email => valid_email)).to be_valid
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
it 'invalidates invalid using `:strict` mode' do
|
|
1078
|
+
expect(DefaultUser.new(:email => invalid_email)).to be_invalid
|
|
1079
|
+
end
|
|
1080
|
+
end
|
|
1081
|
+
|
|
1082
|
+
context 'when `email_validator/rfc` has been required' do
|
|
1083
|
+
before { require 'email_validator/rfc' }
|
|
1084
|
+
|
|
1085
|
+
it 'validates valid using `:rfc` mode' do
|
|
1086
|
+
expect(DefaultUser.new(:email => valid_email)).to be_valid
|
|
1087
|
+
end
|
|
1088
|
+
|
|
1089
|
+
it 'invalidates invalid using `:rfc` mode' do
|
|
1090
|
+
expect(DefaultUser.new(:email => invalid_email)).to be_invalid
|
|
198
1091
|
end
|
|
199
1092
|
end
|
|
200
1093
|
end
|
|
1094
|
+
|
|
1095
|
+
context 'with regexp' do
|
|
1096
|
+
it 'returns a regexp when asked' do
|
|
1097
|
+
expect(described_class.regexp).to be_a(Regexp)
|
|
1098
|
+
end
|
|
1099
|
+
|
|
1100
|
+
it 'returns a strict regexp when asked' do
|
|
1101
|
+
expect(described_class.regexp(:mode => :strict)).to be_a(Regexp)
|
|
1102
|
+
end
|
|
1103
|
+
|
|
1104
|
+
it 'returns a RFC regexp when asked' do
|
|
1105
|
+
expect(described_class.regexp(:mode => :rfc)).to be_a(Regexp)
|
|
1106
|
+
end
|
|
1107
|
+
|
|
1108
|
+
it 'has different regexp for strict and loose' do
|
|
1109
|
+
expect(described_class.regexp(:mode => :strict)).not_to eq(described_class.regexp(:mode => :loose))
|
|
1110
|
+
end
|
|
1111
|
+
|
|
1112
|
+
it 'has different regexp for RFC and loose' do
|
|
1113
|
+
expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :loose))
|
|
1114
|
+
end
|
|
1115
|
+
|
|
1116
|
+
it 'has different regexp for RFC and strict' do
|
|
1117
|
+
expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :strict))
|
|
1118
|
+
end
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1121
|
+
context 'with invalid `:mode`' do
|
|
1122
|
+
it 'raises an error' do
|
|
1123
|
+
expect { described_class.regexp(:mode => :invalid) }.to raise_error(EmailValidator::Error)
|
|
1124
|
+
end
|
|
1125
|
+
end
|
|
201
1126
|
end
|