activesupport_testcase_extras 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f8b60be1e5000d07f15f93b1b44b6007f8734581
4
+ data.tar.gz: 9a4acc5ccb203f3e889af8762a458abf02bd86d5
5
+ SHA512:
6
+ metadata.gz: 3a4bf242cb1c286eb2a082ae037909f94a35f74f812270e32c5fb4964f42f5286b4bc56cb250b1301b7ea2b83d9da9a9ea7662ee89f2181ca11aa227b5808f10
7
+ data.tar.gz: 495f0b96e1d59ba53ec4d0651291ec0d3c94f57a8bd1af1b5f76d28306800c505c40b25fff1cb35ad3f80785f552d70112024a5d3b1c916d09c5e8f774d08d23
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in activesupport_testcase_extras.gemspec
6
+ gemspec
@@ -0,0 +1,34 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ activesupport_testcase_extras (1.0.2)
5
+ activesupport (>= 4.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (5.2.0)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 0.7, < 2)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ concurrent-ruby (1.0.5)
16
+ i18n (1.0.0)
17
+ concurrent-ruby (~> 1.0)
18
+ minitest (5.11.3)
19
+ rake (10.5.0)
20
+ thread_safe (0.3.6)
21
+ tzinfo (1.2.5)
22
+ thread_safe (~> 0.1)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ activesupport_testcase_extras!
29
+ bundler (~> 1.16)
30
+ minitest (~> 5.0)
31
+ rake (~> 10.0)
32
+
33
+ BUNDLED WITH
34
+ 1.16.1
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Beau Barker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ # ActivesupportTestcaseExtras
2
+
3
+ I found it desirable to add additional test and assertion methods to unit tests. This is the result.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'activesupport_testcase_extras'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install activesupport_testcase_extras
20
+
21
+ ## Usage
22
+
23
+ Use the additional methods in your assertions.
24
+
25
+ ```ruby
26
+ test "should require name" do
27
+ assert_required @item, :name
28
+ end
29
+
30
+ test "should limit length of name" do
31
+ assert_max_length @item, :name, 100
32
+ end
33
+
34
+ test "name should be unique" do
35
+ assert_uniqueness @item, :name
36
+ end
37
+ ```
38
+
39
+ ## Development
40
+
41
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
42
+
43
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
44
+
45
+ ## Contributing
46
+
47
+ Bug reports and pull requests are welcome on GitHub at https://github.com/barkerest/activesupport_testcase_extras.
48
+
49
+ ## License
50
+
51
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,28 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "activesupport_testcase_extras/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "activesupport_testcase_extras"
8
+ spec.version = ActivesupportTestcaseExtras::VERSION
9
+ spec.authors = ["Beau Barker"]
10
+ spec.email = ["beau@barkerest.com"]
11
+
12
+ spec.summary = "Provides some additional test methods to ActiveSupport::TestCase."
13
+ spec.homepage = "https://github.com/barkerest/activesupport_testcase_extras"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency 'activesupport' , '>= 4.0'
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.16"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "minitest", "~> 5.0"
28
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "activesupport_testcase_extras"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,6 @@
1
+ require "activesupport_testcase_extras/version"
2
+ require "activesupport_testcase_extras/test_case"
3
+
4
+ module ActivesupportTestcaseExtras
5
+
6
+ end
@@ -0,0 +1,494 @@
1
+ require 'active_support'
2
+
3
+ module ActivesupportTestcaseExtras
4
+ ##
5
+ # Adds some extra assertions and methods for use in tests.
6
+ module TestCase
7
+
8
+ ##
9
+ # Tests a specific field for presence validation.
10
+ #
11
+ # model::
12
+ # This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
13
+ #
14
+ # attribute::
15
+ # This must provide the name of a valid attribute in the model.
16
+ #
17
+ # message::
18
+ # This is optional, but if provided it will be postfixed with the failure reason.
19
+ #
20
+ # regex::
21
+ # This is the regex to match against the error message to ensure that the failure is for the correct reason.
22
+ #
23
+ def assert_required(model, attribute, message = nil, regex = /can't be blank/i)
24
+ original_value = model.send(attribute)
25
+ assert model.valid?, 'Model should be valid to start.'
26
+ is_string = original_value.is_a?(::String)
27
+ setter = :"#{attribute}="
28
+ model.send setter, nil
29
+ assert_not model.valid?, message ? (message + ': (nil)') : "Should not allow #{attribute} to be set to nil."
30
+ assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
31
+ if is_string
32
+ model.send setter, ''
33
+ assert_not model.valid?, message ? (message + ": ('')") : "Should not allow #{attribute} to be set to empty string."
34
+ assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
35
+ model.send setter, ' '
36
+ assert_not model.valid?, message ? (message + ": (' ')") : "Should not allow #{attribute} to be set to blank string."
37
+ assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
38
+ end
39
+ model.send setter, original_value
40
+ assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'."
41
+ end
42
+
43
+ ##
44
+ # Tests a specific field for maximum length restriction.
45
+ #
46
+ # model::
47
+ # This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
48
+ #
49
+ # attribute::
50
+ # This must provide the name of a valid attribute in the model.
51
+ #
52
+ # max_length::
53
+ # This is the maximum valid length for the field.
54
+ #
55
+ # message::
56
+ # This is optional, but if provided it will be postfixed with the failure reason.
57
+ #
58
+ # regex::
59
+ # This is the regex to match against the error message to ensure that the failure is for the correct reason.
60
+ #
61
+ # options::
62
+ # This is a list of options for the validation.
63
+ # Currently :start_with and :end_with are recognized.
64
+ # Use :start_with to specify a prefix for the tested string.
65
+ # Use :end_with to specify a postfix for the tested string.
66
+ # This would be most useful when you value has to follow a format (eg - email address :end_with => '@example.com')
67
+ #
68
+ def assert_max_length(model, attribute, max_length, message = nil, regex = /is too long/i, options = {})
69
+ original_value = model.send(attribute)
70
+ assert model.valid?, 'Model should be valid to start.'
71
+ setter = :"#{attribute}="
72
+
73
+ if message.is_a?(::Hash)
74
+ options = message.merge(options || {})
75
+ message = nil
76
+ end
77
+
78
+ if regex.is_a?(::Hash)
79
+ options = regex.merge(options || {})
80
+ regex = /is too long/i
81
+ end
82
+
83
+ pre = options[:start_with].to_s
84
+ post = options[:end_with].to_s
85
+ len = max_length - pre.length - post.length
86
+
87
+ # try with maximum valid length.
88
+ value = pre + ('a' * len) + post
89
+ model.send setter, value
90
+ assert model.valid?, message ? (message + ": !(#{value.length})") : "Should allow a string of #{value.length} characters."
91
+
92
+ # try with one extra character.
93
+ value = pre + ('a' * (len + 1)) + post
94
+ model.send setter, value
95
+ assert_not model.valid?, message ? (message + ": (#{value.length})") : "Should not allow a string of #{value.length} characters."
96
+ assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
97
+
98
+ model.send setter, original_value
99
+ assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'."
100
+ end
101
+
102
+ ##
103
+ # Tests a specific field for maximum length restriction.
104
+ #
105
+ # model::
106
+ # This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
107
+ #
108
+ # attribute::
109
+ # This must provide the name of a valid attribute in the model.
110
+ #
111
+ # min_length::
112
+ # This is the minimum valid length for the field.
113
+ #
114
+ # message::
115
+ # This is optional, but if provided it will be postfixed with the failure reason.
116
+ #
117
+ # regex::
118
+ # This is the regex to match against the error message to ensure that the failure is for the correct reason.
119
+ #
120
+ # options::
121
+ # This is a list of options for the validation.
122
+ # Currently :start_with and :end_with are recognized.
123
+ # Use :start_with to specify a prefix for the tested string.
124
+ # Use :end_with to specify a postfix for the tested string.
125
+ # This would be most useful when you value has to follow a format (eg - email address :end_with => '@example.com')
126
+ #
127
+ def assert_min_length(model, attribute, min_length, message = nil, regex = /is too short/i, options = {})
128
+ original_value = model.send(attribute)
129
+ assert model.valid?, 'Model should be valid to start.'
130
+ setter = :"#{attribute}="
131
+
132
+ if message.is_a?(::Hash)
133
+ options = message.merge(options || {})
134
+ message = nil
135
+ end
136
+
137
+ if regex.is_a?(::Hash)
138
+ options = regex.merge(options || {})
139
+ regex = /is too short/i
140
+ end
141
+
142
+ pre = options[:start_with].to_s
143
+ post = options[:end_with].to_s
144
+ len = min_length - pre.length - post.length
145
+
146
+ # try with minimum valid length.
147
+ value = pre + ('a' * len) + post
148
+ model.send setter, value
149
+ assert model.valid?, message ? (message + ": !(#{value.length})") : "Should allow a string of #{value.length} characters."
150
+
151
+ # try with one extra character.
152
+ value = pre + ('a' * (len - 1)) + post
153
+ model.send setter, value
154
+ assert_not model.valid?, message ? (message + ": (#{value.length})") : "Should not allow a string of #{value.length} characters."
155
+ assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
156
+
157
+ model.send setter, original_value
158
+ assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'."
159
+ end
160
+
161
+ ##
162
+ # Tests a specific field for uniqueness.
163
+ #
164
+ # model::
165
+ # This must respond to _attribute_ and _attribute=_ as well as _valid?_, _errors_, and _save!_.
166
+ # The model will be saved to perform uniqueness testing.
167
+ #
168
+ # attribute::
169
+ # This must provide the name of a valid attribute in the model.
170
+ #
171
+ # case_sensitive::
172
+ # This determines if changing case should change validation.
173
+ #
174
+ # message::
175
+ # This is optional, but if provided it will be postfixed with the failure reason.
176
+ #
177
+ # regex::
178
+ # This is the regex to match against the error message to ensure that the failure is for the correct reason.
179
+ #
180
+ #
181
+ # alternate_scopes::
182
+ # This is also optional. If provided the keys of the hash will be used to
183
+ # set additional attributes on the model. When these attributes are changed to the alternate
184
+ # values, the model should once again be valid.
185
+ # The alternative scopes are processed one at a time and the original values are restored
186
+ # before moving onto the next scope.
187
+ # A special key :unique_fields, allows you to provide values for other unique fields in the model so they
188
+ # don't affect testing. If the value of :unique_fields is not a hash, then it is put back into the
189
+ # alternate_scopes hash for testing.
190
+ #
191
+ def assert_uniqueness(model, attribute, case_sensitive = false, message = nil, regex = /has already been taken/i, alternate_scopes = {})
192
+ setter = :"#{attribute}="
193
+ original_value = model.send(attribute)
194
+
195
+ assert model.valid?, 'Model should be valid to start.'
196
+
197
+ if case_sensitive.is_a?(::Hash)
198
+ alternate_scopes = case_sensitive.merge(alternate_scopes || {})
199
+ case_sensitive = false
200
+ end
201
+ if message.is_a?(::Hash)
202
+ alternate_scopes = message.merge(alternate_scopes || {})
203
+ message = nil
204
+ end
205
+ if regex.is_a?(::Hash)
206
+ alternate_scopes = regex.merge(alternate_scopes || {})
207
+ regex = /has already been taken/i
208
+ end
209
+
210
+ model.save!
211
+ copy = model.dup
212
+
213
+ other_unique_fields = alternate_scopes.delete(:unique_fields)
214
+ if other_unique_fields
215
+ if other_unique_fields.is_a?(::Hash)
216
+ other_unique_fields.each do |attr,val|
217
+ setter = :"#{attr}="
218
+ copy.send setter, val
219
+ end
220
+ else
221
+ alternate_scopes[:unique_fields] = other_unique_fields
222
+ end
223
+ end
224
+
225
+ assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
226
+ assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
227
+ if original_value.is_a?(::String)
228
+ unless case_sensitive
229
+ copy.send(setter, original_value.upcase)
230
+ assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
231
+ assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
232
+ copy.send(setter, original_value.downcase)
233
+ assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
234
+ assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
235
+ end
236
+ end
237
+
238
+ unless alternate_scopes.blank?
239
+ copy.send(setter, original_value)
240
+ assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
241
+ assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
242
+ alternate_scopes.each do |k,v|
243
+ kset = :"#{k}="
244
+ vorig = copy.send(k)
245
+ copy.send(kset, v)
246
+ assert_equal v, copy.send(k), message ? (message + ": (failed to set #{k})") : "Failed to set #{k}=#{v.inspect}."
247
+ assert copy.valid?, message ? (message + ": !#{k}(#{v})") : "Duplicate model with #{k}=#{v.inspect} should be valid with #{attribute}=#{copy.send(attribute).inspect}."
248
+ copy.send(kset, vorig)
249
+ assert_equal vorig, copy.send(k), message ? (message + ": (failed to reset #{k})") : "Failed to reset #{k}=#{v.inspect}."
250
+ assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
251
+ assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
252
+ end
253
+ end
254
+ end
255
+
256
+ ##
257
+ # Tests a specific field for email verification.
258
+ #
259
+ # model::
260
+ # This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
261
+ #
262
+ # attribute::
263
+ # This must provide the name of a valid attribute in the model.
264
+ #
265
+ # message::
266
+ # This is optional, but if provided it will be postfixed with the failure reason.
267
+ #
268
+ # regex::
269
+ # This is the regex to match against the error message to ensure that the failure is for the correct reason.
270
+ #
271
+ def assert_email_validation(model, attribute, message = nil, regex = /is not a valid email address/i)
272
+ assert model.valid?, 'Model should be valid to start.'
273
+ setter = :"#{attribute}="
274
+ orig = model.send attribute
275
+
276
+ valid = %w(
277
+ user@example.com
278
+ USER@foo.COM
279
+ A_US-ER@foo.bar.org
280
+ first.last@foo.jp
281
+ alice+bob@bax.cn
282
+ )
283
+
284
+ invalid = %w(
285
+ user@example,com
286
+ user_at_foo.org
287
+ user@example.
288
+ user@example.com.
289
+ foo@bar_baz.com
290
+ foo@bar+baz.com
291
+ @example.com
292
+ user@
293
+ user
294
+ user@..com
295
+ user@example..com
296
+ user@.example.com
297
+ user@@example.com
298
+ user@www@example.com
299
+ )
300
+
301
+ valid.each do |addr|
302
+ model.send setter, addr
303
+ assert model.valid?, message ? (message + ': (rejected valid address)') : "Should have accepted #{addr.inspect}."
304
+ end
305
+
306
+ invalid.each do |addr|
307
+ model.send setter, addr
308
+ assert_not model.valid?, message ? (message + ': (accepted invalid address)') : "Should have rejected #{addr.inspect}."
309
+ assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
310
+ end
311
+
312
+ model.send setter, orig
313
+ assert model.valid?, message ? (message + ': (rejected original value)') : "Should have accepted original value of #{orig.inspect}."
314
+
315
+ end
316
+
317
+
318
+ ##
319
+ # Tests a specific field for IP address verification.
320
+ #
321
+ # model::
322
+ # This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
323
+ #
324
+ # attribute::
325
+ # This must provide the name of a valid attribute in the model.
326
+ #
327
+ # mask::
328
+ # This can be one of :allow_mask, :require_mask, or :deny_mask. The default is :allow_mask.
329
+ #
330
+ # message::
331
+ # This is optional, but if provided it will be postfixed with the failure reason.
332
+ #
333
+ # regex::
334
+ # This is the regex to match against the error message to ensure that the failure is for the correct reason.
335
+ # The default value is nil to test for the various default messages.
336
+ #
337
+ def assert_ip_validation(model, attribute, mask = :allow_mask, message = nil, regex = nil)
338
+ assert model.valid?, 'Model should be valid to start.'
339
+ setter = :"#{attribute}="
340
+ orig = model.send attribute
341
+
342
+ valid = %w(
343
+ 0.0.0.0
344
+ 1.2.3.4
345
+ 10.20.30.40
346
+ 255.255.255.255
347
+ 10:20::30:40
348
+ ::1
349
+ 1:2:3:4:5:6:7:8
350
+ A:B:C:D:E:F::
351
+ )
352
+
353
+ invalid = %w(
354
+ localhost
355
+ 100.200.300.400
356
+ 12345::abcde
357
+ 1.2.3.4.5
358
+ 1.2.3
359
+ 0
360
+ 1:2:3:4:5:6:7:8:9:0
361
+ a:b:c:d:e:f:g:h
362
+ )
363
+
364
+ valid.each do |addr|
365
+ if mask == :require_mask
366
+ if addr.index(':')
367
+ addr += '/128'
368
+ else
369
+ addr += '/32'
370
+ end
371
+ end
372
+ model.send setter, addr
373
+ assert model.valid?, message ? (message + ': (rejected valid address)') : "Should have accepted #{addr.inspect}."
374
+ end
375
+
376
+ r = regex ? regex : /is not a valid ip address/i
377
+ invalid.each do |addr|
378
+ if mask == :require_mask
379
+ if addr.index(':')
380
+ addr += '/128'
381
+ else
382
+ addr += '/32'
383
+ end
384
+ end
385
+ model.send setter, addr
386
+ assert_not model.valid?, message ? (message + ': (accepted invalid address)') : "Should have rejected #{addr.inspect}."
387
+ assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
388
+ end
389
+
390
+ if mask == :allow_mask || mask == :require_mask
391
+ address = '127.0.0.0/8'
392
+ model.send setter, address
393
+ assert model.valid?, message ? (message + ': (rejected masked address)') : "Should have accepted #{address.inspect}."
394
+ end
395
+
396
+ if mask == :allow_mask || mask == :deny_mask
397
+ address = '127.0.0.1'
398
+ model.send setter, address
399
+ assert model.valid?, message ? (message + ': (rejected unmasked address)') : "Should have accepted #{address.inspect}."
400
+ end
401
+
402
+ if mask == :require_mask
403
+ r = regex ? regex : /must contain a mask/i
404
+ address = '127.0.0.1'
405
+ model.send setter, address
406
+ assert_not model.valid?, message ? (message + ': (accepted unmasked address)') : "Should have rejected #{address.inspect} for no mask."
407
+ assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
408
+ end
409
+
410
+ if mask == :deny_mask
411
+ r = regex ? regex : /must not contain a mask/i
412
+ address = '127.0.0.0/8'
413
+ model.send setter, address
414
+ assert_not model.valid? message ? (message + ': (accepted masked address)') : "Should have rejected #{address.inspect} for mask."
415
+ assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
416
+ end
417
+
418
+ model.send setter, orig
419
+ assert model.valid?, message ? (message + ': (rejected original value)') : "Should have accepted original value of #{orig.inspect}."
420
+ end
421
+
422
+ ##
423
+ # Tests a specific field for safe name verification.
424
+ #
425
+ # model::
426
+ # This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
427
+ #
428
+ # attribute::
429
+ # This must provide the name of a valid attribute in the model.
430
+ #
431
+ # length::
432
+ # The length of the string to test. Must be greater than 2. Default is 6.
433
+ #
434
+ # message::
435
+ # This is optional, but if provided it will be postfixed with the failure reason.
436
+ #
437
+ # regex::
438
+ # This is the regex to match against the error message to ensure that the failure is for the correct reason.
439
+ # The default value is nil to test for the various default messages.
440
+ #
441
+ def assert_safe_name_validation(model, attribute, length = 6, message = nil, regex = nil)
442
+ assert model.valid?, 'Model should be valid to start.'
443
+ setter = :"#{attribute}="
444
+ orig = model.send attribute
445
+
446
+ assert length > 2, message ? (message + ': (field is too short to test)') : 'Requires a field length greater than 2 to perform tests.'
447
+
448
+ # valid tests.
449
+ mid_length = length - 2
450
+ mid = '' # _z_z_z_z_z_
451
+ while mid.length < mid_length
452
+ if mid.length + 1 < mid_length
453
+ mid += '_z'
454
+ else
455
+ mid += '_'
456
+ end
457
+ end
458
+
459
+ [
460
+ 'a' * length,
461
+ 'a' + ('1' * (length - 1)),
462
+ 'a' + mid + 'a',
463
+ 'a' + mid + '1'
464
+ ].each do |val|
465
+ model.send setter, val
466
+ assert model.valid?, message ? (message + ': (rejected valid string)') : "Should have accepted #{val.inspect}."
467
+ val.upcase!
468
+ model.send setter, val
469
+ assert model.valid?, message ? (message + ': (rejected valid string)') : "Should have accepted #{val.inspect}."
470
+ end
471
+
472
+ # invalid tests.
473
+ {
474
+ '_' + ('a' * (length - 1)) => /must start with a letter/i,
475
+ '1' + ('a' * (length - 1)) => /must start with a letter/i,
476
+ ('a' * (length - 1)) + '_' => /must not end with an underscore/i,
477
+ ('a' * (length - 2)) + '-' + 'a' => /must contain only letters, numbers, and underscore/i,
478
+ ('a' * (length - 2)) + '#' + 'a' => /must contain only letters, numbers, and underscore/i,
479
+ ('a' * (length - 2)) + ' ' + 'a' => /must contain only letters, numbers, and underscore/i
480
+ }.each do |val, reg|
481
+ r = regex ? regex : reg
482
+ model.send setter, val
483
+ assert_not model.valid?, message ? (message + ': (accepted invalid string)') : "Should have rejected #{val.inspect}."
484
+ assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : "Did not fail for expected reason on #{val.inspect}."
485
+ end
486
+
487
+ model.send setter, orig
488
+ assert model.valid?, message ? (message + ': (rejected original value)') : "Should have accepted original value of #{orig.inspect}."
489
+ end
490
+
491
+ end
492
+ end
493
+
494
+ ActiveSupport::TestCase.include ActivesupportTestcaseExtras::TestCase
@@ -0,0 +1,3 @@
1
+ module ActivesupportTestcaseExtras
2
+ VERSION = "1.0.2"
3
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activesupport_testcase_extras
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Beau Barker
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-04-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description:
70
+ email:
71
+ - beau@barkerest.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - activesupport_testcase_extras.gemspec
84
+ - bin/console
85
+ - bin/setup
86
+ - lib/activesupport_testcase_extras.rb
87
+ - lib/activesupport_testcase_extras/test_case.rb
88
+ - lib/activesupport_testcase_extras/version.rb
89
+ homepage: https://github.com/barkerest/activesupport_testcase_extras
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.6.13
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Provides some additional test methods to ActiveSupport::TestCase.
113
+ test_files: []