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