minitest-sequel 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+ require "minitest/sequel"
2
+
3
+ # reopening to add helpers functionality
4
+ class Minitest::Spec
5
+
6
+ # Enables quick tests to ensure that the basic CRUD functionality is working correctly for a Model
7
+ #
8
+ # let(:m) { User.make }
9
+ #
10
+ # ensure_working_CRUD(User, :username)
11
+ #
12
+ # NOTE!
13
+ #
14
+ # * the passed `_model` argument must be the actual Model class and NOT a string or symbol
15
+ # * the passed attribute `_attr` must be a String attribute or the tests will fail
16
+ #
17
+ # **DEPENDENCIES**
18
+ #
19
+ # this test depends upon being able to create a new model instance for each test via using
20
+ # Sequel Factory's `#make()` method
21
+ #
22
+ def self.ensure_working_CRUD(model, attr)
23
+
24
+ describe "a valid CRUD model" do
25
+
26
+ it "can create a #{model}" do
27
+ m = model.send(:make)
28
+ assert_instance_of(_model, m, "CRUD:create - expected #{m.class} to be an instance of #{model}")
29
+ assert_empty(m.errors, "CRUD:create - expected .errors to be empty, but was: [#{m.errors.inspect}]")
30
+ end
31
+
32
+ it "can read a #{model}" do
33
+ m = model.send(:make)
34
+ res = model.send :first
35
+ assert_instance_of(model, m, "CRUD:read - expected #{res.class} to be an instance of #{model}")
36
+ assert_equal(m, res, "CRUD:read - expected [#{m.inspect}] to equal [#{res.inspect}]")
37
+ end
38
+
39
+ it "can update a #{model}" do
40
+ m = model.send(:make)
41
+ tmp_str = "#{m.send(attr.to_sym)} Updated"
42
+ res = model.send(:first)
43
+
44
+ assert_equal(m, res, "CRUD:update - expected [#{m.inspect}] to equal [#{res.inspect}]")
45
+ res.send("#{attr}=", tmp_str)
46
+ res.save
47
+
48
+ res2 = model.send(:first)
49
+ assert_equal(tmp_str, res2.send(attr.to_sym), "CRUD:update - expected [#{res2.send(attr.to_sym)}] to equal the updated string: [#{tmp_str}]")
50
+ end
51
+
52
+ it "can destroy a #{model}" do
53
+ m = model.send(:make)
54
+ if m.respond_to?(:deleted_at)
55
+ assert_nil(m.deleted_at, "CRUD:delete - expected m.deleted_at to be nil, but was [#{m.deleted_at}]")
56
+ end
57
+ assert(m.destroy, "CRUD:delete - expected m.destroy to return true")
58
+ res = model.send(:first)
59
+ assert_nil(res, "CRUD:delete - expected #{model}.first to return nil, but was: [#{res.inspect}]")
60
+ if m.respond_to?(:deleted_at)
61
+ refute_nil(m.deleted_at, "CRUD:delete - expected m.deleted_at to be NOT be nil")
62
+ assert_instance_of(Time, m.deleted_at, "CRUD:delete - expected m.deleted_at to be an instance of Time")
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,166 @@
1
+ require "minitest/sequel"
2
+
3
+ # reopening to add validations functionality
4
+ module Minitest::Assertions
5
+
6
+ # Test if a model instance is timestamped via .plugin(:timestamps)
7
+ #
8
+ # let(:m) { Post.create(title: "Dummy") }
9
+ # proc { assert_timestamped_model_instance(m) }.wont_have_error
10
+ #
11
+ # You can also test if an updated record is correctly timestamped
12
+ #
13
+ # m.title = "Updated"
14
+ # m.save
15
+ # proc { assert_timestamped_model_instance(m, updated_record: true) }.wont_have_error
16
+ #
17
+ # Or alternatively test if an updated record is wrongly timestamped
18
+ #
19
+ # let(:m) { Post.create(title: "Dummy", updated_at: Time.now) }
20
+ # proc { assert_timestamped_model_instance(m, updated_record: false) }.must_have_error(/expected #.updated_at to be NIL on new record/)
21
+ #
22
+ #
23
+ def assert_timestamped_model_instance(model, opts = {})
24
+ model_class = model.class
25
+ # 1. test for Timestamps plugin
26
+ plugs = model_class.instance_variable_get("@plugins").map(&:to_s)
27
+ if plugs.include?("Sequel::Plugins::Timestamps")
28
+ # 2. test for created_at / :updated_at columns
29
+ assert_have_column(model, :created_at, {}, "AssertTimestampedModelInstance - expected model to have column :created_at, Debug: [#{model.inspect}]")
30
+ assert_have_column(model, :updated_at, {}, "AssertTimestampedModelInstance - expected model to have column :updated_at, Debug: [#{model.inspect}]")
31
+
32
+ if opts[:updated_record]
33
+ # 4. updated record
34
+ assert_instance_of(Time, model.created_at, "AssertTimestampedModelInstance:created_at - expected #created_at to be an instance of Time on updated record")
35
+ assert_instance_of(Time, model.updated_at, "AssertTimestampedModelInstance:updated_at - expected #updated_at to be an instance of Time on updated record")
36
+ else
37
+ # 3. initial record
38
+ assert_instance_of(Time, model.created_at, "AssertTimestampedModelInstance:created_at - expected #created_at to be an instance of Time on new record")
39
+ proc {
40
+ assert_nil(model.updated_at, "AssertTimestampedModelInstance:updated - expected #updated_at to be NIL on new record")
41
+ }.wont_have_error
42
+ end
43
+ else
44
+ raise(Minitest::Assertion, "Not a plugin(:timestamps) model, available plugins are: #{plugs.inspect}")
45
+ end
46
+ end
47
+
48
+ # Test if a model class is timestamped with .plugin(:timestamps)
49
+ #
50
+ # # Declared locally in the Model
51
+ # class Comment < Sequel::Model
52
+ # plugin(:timestamps)
53
+ # end
54
+ # proc { assert_timestamped_model(Comment) }.wont_have_error
55
+ #
56
+ # # on a non-timestamped model
57
+ # class Post < Sequel::Model; end
58
+ # proc { assert_timestamped_model(Post) }.must_have_error(/Not a \.plugin\(:timestamps\) model, available plugins are/)
59
+ #
60
+ #
61
+ # NOTE!
62
+ #
63
+ # You can also pass attributes to the created model in the tests via the `opts` hash like this:
64
+ #
65
+ # proc { assert_timestamped_model(Comment, {body: "I think...", email: "e@email.com"}) }.wont_have_error
66
+ #
67
+ #
68
+ def assert_timestamped_model(model, opts = {})
69
+ m = model.create(opts)
70
+ # 1. test for Timestamps plugin
71
+ plugs = model.instance_variable_get("@plugins").map(&:to_s)
72
+ if plugs.include?("Sequel::Plugins::Timestamps")
73
+ # 2. test for created_at / :updated_at columns
74
+ assert_have_column(m, :created_at, {}, "AssertTimestampedModel - expected model to have column :created_at. Debug: [#{m.inspect}]")
75
+ assert_have_column(m, :updated_at, {}, "AssertTimestampedModel - expected model to have column :updated_at. Debug: [#{m.inspect}]")
76
+
77
+ # 3. initial record
78
+ assert_instance_of(Time, m.created_at, "AssertTimestampedModel:created_at - expected #created_at to be an instance of Time on new record. Debug: [#{m.inspect}]")
79
+ assert_instance_of(NilClass, m.updated_at, "AssertTimestampedModel:updated_at - expected #updated_at to be an instance of NilClass on new record. Debug: [#{m.inspect}]")
80
+
81
+ # 4. updated record
82
+ # old_ts = m.created_at
83
+ # sleep 1 # TODO: could this be converted to timecop or similar?
84
+ m.title = "#{m.title} updated"
85
+ assert(m.save, "AssertTimestampedModel:#save - updated model failed. Debug: [#{m.inspect}]")
86
+ assert_instance_of(Time, m.created_at, "AssertTimestampedModel:created_at - expected #created_at to be an instance of Time on updated record. Debug: [#{m.inspect}]")
87
+ assert_instance_of(Time, m.updated_at, "AssertTimestampedModel:updated_at - expected #updated_at to be an instance of Time on updated record. Debug: [#{m.inspect}]")
88
+ # assert_equal(old_ts, m.created_at, "AssertTimestampedModel - expected the :created_at timestamp to be unchanged")
89
+ else
90
+ raise(Minitest::Assertion, "Not a plugin(:timestamps) model, available plugins are: #{plugs.inspect}")
91
+ end
92
+ end
93
+
94
+ # Test if a model class is paranoid with .plugin(:paranoid) via [Sequel-Paranoid](https://github.com/sdepold/sequel-paranoid)
95
+ #
96
+ # # Declared locally in the Model
97
+ # class Comment < Sequel::Model
98
+ # plugin(:paranoid)
99
+ # end
100
+ # proc { assert_paranoid_model(Comment) }.wont_have_error
101
+ #
102
+ # # on a non-paranoid model
103
+ # class Post < Sequel::Model; end
104
+ # proc { assert_paranoid_model(Post) }.must_have_error(/Not a plugin\(:paranoid\) model, available plugins are/)
105
+ #
106
+ #
107
+ # NOTE!
108
+ #
109
+ # You can also pass attributes to the created model in the tests via the `opts` hash like this:
110
+ #
111
+ # proc { assert_timestamped_model(Comment, {body: "I think...", email: "e@email.com"}) }.wont_have_error
112
+ #
113
+ #
114
+ def assert_paranoid_model(model, opts = {})
115
+ m = model.create(opts)
116
+ # 1. test for Paranoid plugin
117
+ plugs = model.instance_variable_get("@plugins").map(&:to_s)
118
+ if plugs.include?("Sequel::Plugins::Paranoid")
119
+ assert_nil(m.deleted_at, "AssertParanoidModel:deleted_at - expected #deleted_at to be NIL on new model")
120
+ # after update
121
+ assert(m.save, "AssertParanoidModel:save - updated model failed. Debug: [#{m.inspect}]")
122
+ assert_nil(m.deleted_at, "AssertParanoidModel:deleted_at - expected #deleted_at to be NIL on updated model")
123
+ # after destroy
124
+ assert(m.destroy, "AssertParanoidModel:destroy - destroy model failed. Debug: [#{m.inspect}]")
125
+ assert_instance_of(Time, m.deleted_at, "AssertParanoidModel:deleted_at - expected #deleted_at to be instance of Time on destroyed model, Debug: [#{m.inspect}]")
126
+ else
127
+ raise(Minitest::Assertion, "Not a plugin(:paranoid) model, available plugins are: #{plugs.inspect}")
128
+ end
129
+ end
130
+
131
+
132
+
133
+ # Test to ensure the current model is NOT a :timestamped model
134
+ #
135
+ # it { refute_timestamped_model(Post) }
136
+ #
137
+ def refute_timestamped_model(model, opts = {})
138
+ plugs = model.instance_variable_get("@plugins").map(&:to_s)
139
+ refute_includes(plugs, "Sequel::Plugins::Timestamps", "RefuteTimestampedModel - expected #{model} to NOT be a :timestamped model, but it was, Debug: [#{plugs.inspect}]")
140
+ end
141
+
142
+ # Test to ensure the current model is NOT a :paranoid model
143
+ #
144
+ # it { refute_paranoid_model(Post) }
145
+ #
146
+ def refute_paranoid_model(model)
147
+ plugs = model.instance_variable_get("@plugins").map(&:to_s)
148
+ refute_includes(plugs, "Sequel::Plugins::Paranoid", "RefuteParanoidModel - expected #{model} to NOT be a :paranoid model, but it was, Debug: [#{plugs.inspect}]")
149
+ end
150
+
151
+
152
+ end
153
+
154
+
155
+ # add support for Spec syntax
156
+ module Minitest::Expectations
157
+
158
+ infect_an_assertion :assert_timestamped_model, :must_be_timestamped_model, :reverse
159
+ infect_an_assertion :assert_paranoid_model, :must_be_paranoid_model, :reverse
160
+ infect_an_assertion :assert_paranoid_model, :must_be_a_paranoid_model, :reverse
161
+
162
+ infect_an_assertion :refute_timestamped_model, :wont_be_timestamped_model, :reverse
163
+ infect_an_assertion :refute_timestamped_model, :wont_be_a_timestamped_model, :reverse
164
+ infect_an_assertion :refute_paranoid_model, :wont_be_paranoid_model, :reverse
165
+ infect_an_assertion :refute_paranoid_model, :wont_be_a_paranoid_model, :reverse
166
+ end
@@ -1,212 +1,212 @@
1
- require 'minitest/sequel'
1
+ require "minitest/sequel"
2
2
 
3
3
  # reopening to add validations functionality
4
4
  module Minitest::Assertions
5
-
5
+
6
6
  # Test for validating presence of a model attribute
7
- #
7
+ #
8
8
  # it { assert_validates_presence(model, :title) }
9
9
  # it { model.must_validate_presence_of(:title, { message: '...' }) }
10
- #
10
+ #
11
11
  def assert_validates_presence(obj, attribute, opts = {}, msg = nil)
12
12
  assert_validates(obj, :presence, attribute, opts, msg)
13
13
  end
14
14
  alias_method :assert_validates_presence_of, :assert_validates_presence
15
-
15
+
16
16
  # Test for validating the length of a model's attribute.
17
- #
17
+ #
18
18
  # Available options:
19
- #
19
+ #
20
20
  # * :message - The message to use (no default, overrides :nil_message, :too_long, :too_short, and :wrong_length options if present)
21
21
  # * :nil_message - The message to use use if :maximum option is used and the value is nil (default: 'is not present')
22
- #
22
+ #
23
23
  # * :too_long - The message to use use if it the value is too long (default: 'is too long')
24
- #
24
+ #
25
25
  # * :too_short - The message to use use if it the value is too short (default: 'is too short')
26
- #
26
+ #
27
27
  # * :wrong_length - The message to use use if it the value is not valid (default: 'is the wrong length')
28
- #
28
+ #
29
29
  # Size related options:
30
- #
30
+ #
31
31
  # * :is - The exact size required for the value to be valid (no default)
32
- #
32
+ #
33
33
  # * :minimum - The minimum size allowed for the value (no default)
34
- #
34
+ #
35
35
  # * :maximum - The maximum size allowed for the value (no default)
36
36
  #
37
37
  # * :within - The array/range that must include the size of the value for it to be valid (no default)
38
- #
39
- #
38
+ #
39
+ #
40
40
  # it { assert_validates_length(model, :title, { maximum: 12 }) }
41
41
  # it { model.must_validate_length_of(:title, { within: 4..12 }) }
42
- #
42
+ #
43
43
  def assert_validates_length(obj, attribute, opts = {}, msg = nil)
44
44
  assert_validates(obj, :length, attribute, opts, msg)
45
45
  end
46
46
  alias_method :assert_validates_length_of, :assert_validates_length
47
-
47
+
48
48
  # Test for validating the exact length of a model's attribute.
49
- #
49
+ #
50
50
  # it { assert_validates_exact_length(model, :title, 12, { message: '...' }) }
51
51
  # it { model.must_validate_exact_length_of(:title, 12, { message: '...' }) }
52
- #
52
+ #
53
53
  def assert_validates_exact_length(obj, attribute, exact_length, opts = {}, msg = nil)
54
- opts.merge!({ is: exact_length })
54
+ opts.merge!(is: exact_length)
55
55
  assert_validates(obj, :length, attribute, opts, msg)
56
56
  end
57
57
  alias_method :assert_validates_exact_length_of, :assert_validates_exact_length
58
-
58
+
59
59
  # Test for validating the exact length of a model's attribute.
60
- #
60
+ #
61
61
  # it { assert_validates_length_range(model, :title, 4..12, { message: '...' }) }
62
62
  # it { model.must_validate_length_range_of(:title, 4..12, { message: '...' }) }
63
- #
63
+ #
64
64
  def assert_validates_length_range(obj, attribute, range, opts = {}, msg = nil)
65
- opts.merge!({ within: range })
65
+ opts.merge!(within: range)
66
66
  assert_validates(obj, :length, attribute, opts, msg)
67
67
  end
68
68
  alias_method :assert_validates_length_range_of, :assert_validates_length_range
69
-
69
+
70
70
  # Test for validating the maximum length of a model's attribute.
71
- #
71
+ #
72
72
  # it { assert_validates_max_length(model, :title, 12, { message: '...' }) }
73
73
  # it { model.must_validate_max_length_of(:title, 12, { message: '...' }) }
74
- #
74
+ #
75
75
  def assert_validates_max_length(obj, attribute, max_length, opts = {}, msg = nil)
76
- opts.merge!({ maximum: max_length })
76
+ opts.merge!(maximum: max_length)
77
77
  assert_validates(obj, :length, attribute, opts, msg)
78
78
  end
79
79
  alias_method :assert_validates_max_length_of, :assert_validates_max_length
80
80
 
81
81
  # Test for validating the minimum length of a model's attribute.
82
- #
82
+ #
83
83
  # it { assert_validates_min_length(model, :title, 12, { message: '...' }) }
84
84
  # it { model.must_validate_min_length_of(:title, 12, { message: '...' }) }
85
- #
85
+ #
86
86
  def assert_validates_min_length(obj, attribute, min_length, opts = {}, msg = nil)
87
- opts.merge!({ minimum: min_length })
87
+ opts.merge!(minimum: min_length)
88
88
  assert_validates(obj, :length, attribute, opts, msg)
89
89
  end
90
90
  alias_method :assert_validates_min_length_of, :assert_validates_min_length
91
-
91
+
92
92
  # Test for validating the format of a model's attribute with a regexp.
93
- #
93
+ #
94
94
  # it { assert_validates_format(model, :title, 12, { with: /[a-z+]/ }) }
95
95
  # it { model.must_validate_format_of(:title, 12, { with: /[a-z]+/ }) }
96
- #
96
+ #
97
97
  def assert_validates_format(obj, attribute, opts = {}, msg = nil)
98
98
  assert_validates(obj, :format, attribute, opts, msg)
99
99
  end
100
100
  alias_method :assert_validates_format_of, :assert_validates_format
101
-
101
+
102
102
  # Test for validating that a model's attribute is within a specified range or set of values.
103
- #
103
+ #
104
104
  # it { assert_validates_inclusion(model, :status, { in: [:a, :b, :c] }) }
105
105
  # it { model.must_validate_inclusion_of(:status, { in: [:a, :b, :c] }) }
106
- #
106
+ #
107
107
  def assert_validates_inclusion(obj, attribute, opts = {}, msg = nil)
108
108
  assert_validates(obj, :inclusion, attribute, opts, msg)
109
109
  end
110
110
  alias_method :assert_validates_inclusion_of, :assert_validates_inclusion
111
-
111
+
112
112
  # Test for validating that a a model's attribute is an integer.
113
- #
113
+ #
114
114
  # it { assert_validates_integer(model, :author_id, { message: '...' }) }
115
115
  # it { model.must_validate_integer_of(:author_id, { message: '...' }) }
116
- #
116
+ #
117
117
  def assert_validates_integer(obj, attribute, opts = {}, msg = nil)
118
- opts.merge!({ only_integer: true })
118
+ opts.merge!(only_integer: true)
119
119
  assert_validates(obj, :numericality, attribute, opts, msg)
120
120
  end
121
-
121
+
122
122
  # Test for validating that a model's attribute is numeric (number).
123
- #
123
+ #
124
124
  # it { assert_validates_numericality(model, :author_id, { message: '...' }) }
125
125
  # it { model.must_validate_numericality_of(:author_id, { message: '...' }) }
126
- #
126
+ #
127
127
  def assert_validates_numericality(obj, attribute, opts = {}, msg = nil)
128
128
  assert_validates(obj, :numericality, attribute, opts, msg)
129
129
  end
130
130
  alias_method :assert_validates_numericality_of, :assert_validates_numericality
131
-
131
+
132
132
  # Test for validating that a model's attribute is unique.
133
- #
133
+ #
134
134
  # it { assert_validates_uniqueness(model, :urlslug, { message: '...' }) }
135
135
  # it { model.must_validate_uniqueness_of(:urlslug, { message: '...' }) }
136
- #
136
+ #
137
137
  def assert_validates_uniqueness(obj, attribute, opts = {}, msg = nil)
138
138
  assert_validates(obj, :uniqueness, attribute, opts, msg)
139
139
  end
140
140
  alias_method :assert_validates_uniqueness_of, :assert_validates_uniqueness
141
-
141
+
142
142
  # Validates acceptance of an attribute. Just checks that the value is equal to the :accept option. This method is unique in that :allow_nil is assumed to be true instead of false.
143
-
143
+
144
144
  # Test for validating the acceptance of a model's attribute.
145
- #
145
+ #
146
146
  # it { assert_validates_acceptance(Order.new, :toc, { message: '...' }) }
147
147
  # it { model.must_validate_acceptance_of(:toc, { message: '...' }) }
148
- #
148
+ #
149
149
  def assert_validates_acceptance(obj, attribute, opts = {}, msg = nil)
150
150
  assert_validates(obj, :acceptance, attribute, opts, msg)
151
151
  end
152
152
  alias_method :assert_validates_acceptance_of, :assert_validates_acceptance
153
-
153
+
154
154
  # Test for validating the confirmation of a model's attribute.
155
- #
155
+ #
156
156
  # it { assert_validates_confirmation(User.new, :password, { message: '...' }) }
157
157
  # it { User.new.must_validate_confirmation_of(:password, { message: '...' }) }
158
- #
158
+ #
159
159
  def assert_validates_confirmation(obj, attribute, opts = {}, msg = nil)
160
160
  assert_validates(obj, :confirmation, attribute, opts, msg)
161
161
  end
162
162
  alias_method :assert_validates_confirmation_of, :assert_validates_confirmation
163
-
163
+
164
164
  # Base test for validations of a model, used mainly as a shortcut for other assertions
165
- def assert_validates(obj, validation_type, attribute, opts = {}, msg = nil, &blk)
166
- msg = msg.nil? ? '' : "#{msg}\n"
165
+ def assert_validates(obj, validation_type, attribute, opts = {}, msg = nil)
166
+ msg = msg.nil? ? "" : "#{msg}\n"
167
167
  err_msg = []
168
168
  conf_msg = []
169
169
  unless obj.respond_to?(attribute)
170
- assert(false, "Column :#{attribute} is not defined in #{obj.class.to_s}")
170
+ assert(false, "Column :#{attribute} is not defined in #{obj.class}")
171
171
  end
172
-
172
+
173
173
  msg << "Expected #{obj.class} to validate :#{validation_type} for :#{attribute} column"
174
-
174
+
175
175
  if _validated_model?(obj)
176
-
176
+
177
177
  if _validated_column?(obj, attribute)
178
-
179
- # checks if the model column is validated by the validation type
178
+
179
+ # checks if the model column is validated by the validation type
180
180
  if _validated_with_validation_type?(obj, attribute, validation_type)
181
181
  matching = true
182
-
182
+
183
183
  # bail out if options provided are invalid
184
184
  val_opts = _valid_validation_options(validation_type)
185
-
186
- invalid_opts = opts.keys.reject { |o| val_opts.include?(o) }
185
+
186
+ invalid_opts = opts.keys.reject { |o| val_opts.include?(o) }
187
187
  unless invalid_opts.empty?
188
188
  msg << ", but the following invalid option(s) was found: { "
189
189
  invalid_opts.each { |o| msg << "#{o.inspect}; " }
190
190
  msg << " }. Valid options are: #{val_opts.inspect}"
191
191
  assert(false, msg)
192
192
  end
193
-
193
+
194
194
  h = _validation_types_hash_for_column(obj, attribute)
195
195
  _available_validation_options.each do |ov|
196
196
  unless opts[ov].nil?
197
197
  expected = (h[validation_type][ov].to_s == opts[ov].to_s)
198
- conf_msg << "#{ov}: '#{opts[ov]}'"
198
+ conf_msg << "#{ov}: '#{opts[ov]}'"
199
199
  unless expected
200
200
  err_msg << "#{ov}: '#{h[validation_type][ov]}'"
201
201
  end
202
202
  matching &&= expected
203
203
  end
204
204
  end
205
-
205
+
206
206
  msg = msg << " with: { #{conf_msg.join(', ')} }" unless conf_msg.empty?
207
207
  msg << " but found: { #{err_msg.join(', ')} }" unless err_msg.empty?
208
208
  assert(matching, msg)
209
-
209
+
210
210
  else
211
211
  msg << ", but no :#{validation_type} validation is defined for :#{attribute}"
212
212
  assert(false, msg)
@@ -216,184 +216,179 @@ module Minitest::Assertions
216
216
  assert(false, msg)
217
217
  end
218
218
  else
219
- assert(false, "No validations defined in #{obj.class.to_s}")
219
+ assert(false, "No validations defined in #{obj.class}")
220
220
  end
221
221
  end
222
-
223
-
222
+
223
+
224
224
  # Test for validating presence of a model attribute
225
- #
225
+ #
226
226
  # it { refute_validates_presence(model, :title) }
227
227
  # it { model.must_validate_presence_of(:title, { message: '...' }) }
228
- #
228
+ #
229
229
  def refute_validates_presence(obj, attribute, opts = {}, msg = nil)
230
230
  refute_validates(obj, :presence, attribute, opts, msg)
231
231
  end
232
232
  alias_method :refute_validates_presence_of, :refute_validates_presence
233
-
233
+
234
234
  # Test for validating the length of a model's attribute.
235
- #
235
+ #
236
236
  # Available options:
237
- #
238
- # :message :: The message to use (no default, overrides :nil_message, :too_long,
237
+ #
238
+ # :message :: The message to use (no default, overrides :nil_message, :too_long,
239
239
  # :too_short, and :wrong_length options if present)
240
- #
241
- # :nil_message :: The message to use use if :maximum option is used and the value is nil
240
+ #
241
+ # :nil_message :: The message to use use if :maximum option is used and the value is nil
242
242
  # (default: 'is not present')
243
- #
243
+ #
244
244
  # :too_long :: The message to use use if it the value is too long (default: 'is too long')
245
- #
246
- # :too_short :: The message to use use if it the value is too short
245
+ #
246
+ # :too_short :: The message to use use if it the value is too short
247
247
  # (default: 'is too short')
248
- #
249
- # :wrong_length :: The message to use use if it the value is not valid
248
+ #
249
+ # :wrong_length :: The message to use use if it the value is not valid
250
250
  # (default: 'is the wrong length')
251
- #
251
+ #
252
252
  # SIZE RELATED OPTIONS:
253
- #
253
+ #
254
254
  # :is :: The exact size required for the value to be valid (no default)
255
255
  # :minimum :: The minimum size allowed for the value (no default)
256
256
  # :maximum :: The maximum size allowed for the value (no default)
257
- # :within :: The array/range that must include the size of the value for it to be valid
257
+ # :within :: The array/range that must include the size of the value for it to be valid
258
258
  # (no default)
259
- #
259
+ #
260
260
  # it { refute_validates_length(model, :title, { maximum: 12 }) }
261
261
  # it { model.must_validate_length_of(:title, { within: 4..12 }) }
262
- #
262
+ #
263
263
  def refute_validates_length(obj, attribute, opts = {}, msg = nil)
264
264
  refute_validates(obj, :length, attribute, opts, msg)
265
265
  end
266
266
  alias_method :refute_validates_length_of, :refute_validates_length
267
-
267
+
268
268
  # Test for validating the exact length of a model's attribute.
269
- #
269
+ #
270
270
  # it { refute_validates_exact_length(model, :title, 12, { message: '...' }) }
271
271
  # it { model.must_validate_exact_length_of(:title, 12, { message: '...' }) }
272
- #
272
+ #
273
273
  def refute_validates_exact_length(obj, attribute, exact_length, opts = {}, msg = nil)
274
- opts.merge!({ is: exact_length })
274
+ opts.merge!(is: exact_length)
275
275
  refute_validates(obj, :length, attribute, opts, msg)
276
276
  end
277
277
  alias_method :refute_validates_exact_length_of, :refute_validates_exact_length
278
-
278
+
279
279
  # Test for validating the exact length of a model's attribute.
280
- #
280
+ #
281
281
  # it { refute_validates_length_range(model, :title, 4..12, { message: '...' }) }
282
282
  # it { model.must_validate_length_range_of(:title, 4..12, { message: '...' }) }
283
- #
283
+ #
284
284
  def refute_validates_length_range(obj, attribute, range, opts = {}, msg = nil)
285
- opts.merge!({ within: range })
285
+ opts.merge!(within: range)
286
286
  refute_validates(obj, :length, attribute, opts, msg)
287
287
  end
288
288
  alias_method :refute_validates_length_range_of, :refute_validates_length_range
289
-
289
+
290
290
  # Test for validating the maximum length of a model's attribute.
291
- #
291
+ #
292
292
  # it { refute_validates_max_length(model, :title, 12, { message: '...' }) }
293
293
  # it { model.must_validate_max_length_of(:title, 12, { message: '...' }) }
294
- #
294
+ #
295
295
  def refute_validates_max_length(obj, attribute, max_length, opts = {}, msg = nil)
296
- opts.merge!({ maximum: max_length })
296
+ opts.merge!(maximum: max_length)
297
297
  refute_validates(obj, :length, attribute, opts, msg)
298
298
  end
299
299
  alias_method :refute_validates_max_length_of, :refute_validates_max_length
300
300
 
301
301
  # Test for validating the minimum length of a model's attribute.
302
- #
302
+ #
303
303
  # it { refute_validates_min_length(model, :title, 12, { message: '...' }) }
304
304
  # it { model.must_validate_min_length_of(:title, 12, { message: '...' }) }
305
- #
305
+ #
306
306
  def refute_validates_min_length(obj, attribute, min_length, opts = {}, msg = nil)
307
- opts.merge!({ minimum: min_length })
307
+ opts.merge!(minimum: min_length)
308
308
  refute_validates(obj, :length, attribute, opts, msg)
309
309
  end
310
310
  alias_method :refute_validates_min_length_of, :refute_validates_min_length
311
-
311
+
312
312
  # Test for validating the format of a model's attribute with a regexp.
313
- #
313
+ #
314
314
  # it { refute_validates_format(model, :title, 12, { with: /[a-z+]/ }) }
315
315
  # it { model.must_validate_format_of(:title, 12, { with: /[a-z]+/ }) }
316
- #
316
+ #
317
317
  def refute_validates_format(obj, attribute, opts = {}, msg = nil)
318
318
  refute_validates(obj, :format, attribute, opts, msg)
319
319
  end
320
320
  alias_method :refute_validates_format_of, :refute_validates_format
321
-
321
+
322
322
  # Test for validating that a model's attribute is within a specified range or set of values.
323
- #
323
+ #
324
324
  # it { refute_validates_inclusion(model, :status, { in: [:a, :b, :c] }) }
325
325
  # it { model.must_validate_inclusion_of(:status, { in: [:a, :b, :c] }) }
326
- #
326
+ #
327
327
  def refute_validates_inclusion(obj, attribute, opts = {}, msg = nil)
328
328
  refute_validates(obj, :inclusion, attribute, opts, msg)
329
329
  end
330
330
  alias_method :refute_validates_inclusion_of, :refute_validates_inclusion
331
-
331
+
332
332
  # Test for validating that a a model's attribute is an integer.
333
- #
333
+ #
334
334
  # it { refute_validates_integer(model, :author_id, { message: '...' }) }
335
335
  # it { model.must_validate_integer_of(:author_id, { message: '...' }) }
336
- #
336
+ #
337
337
  def refute_validates_integer(obj, attribute, opts = {}, msg = nil)
338
- opts.merge!({ only_integer: true })
338
+ opts.merge!(only_integer: true)
339
339
  refute_validates(obj, :numericality, attribute, opts, msg)
340
340
  end
341
-
341
+
342
342
  # Test for validating that a model's attribute is numeric (number).
343
- #
343
+ #
344
344
  # it { refute_validates_numericality(model, :author_id, { message: '...' }) }
345
345
  # it { model.must_validate_numericality_of(:author_id, { message: '...' }) }
346
- #
346
+ #
347
347
  def refute_validates_numericality(obj, attribute, opts = {}, msg = nil)
348
348
  refute_validates(obj, :numericality, attribute, opts, msg)
349
349
  end
350
350
  alias_method :refute_validates_numericality_of, :refute_validates_numericality
351
-
351
+
352
352
  # Test for validating that a model's attribute is unique.
353
- #
353
+ #
354
354
  # it { refute_validates_uniqueness(model, :urlslug, { message: '...' }) }
355
355
  # it { model.must_validate_uniqueness_of(:urlslug, { message: '...' }) }
356
- #
356
+ #
357
357
  def refute_validates_uniqueness(obj, attribute, opts = {}, msg = nil)
358
358
  refute_validates(obj, :uniqueness, attribute, opts, msg)
359
359
  end
360
360
  alias_method :refute_validates_uniqueness_of, :refute_validates_uniqueness
361
-
361
+
362
362
  # Validates acceptance of an attribute. Just checks that the value is equal to the :accept option. This method is unique in that :allow_nil is assumed to be true instead of false.
363
-
363
+
364
364
  # Test for validating the acceptance of a model's attribute.
365
- #
365
+ #
366
366
  # it { refute_validates_acceptance(Order.new, :toc, { message: '...' }) }
367
367
  # it { model.must_validate_acceptance_of(:toc, { message: '...' }) }
368
- #
368
+ #
369
369
  def refute_validates_acceptance(obj, attribute, opts = {}, msg = nil)
370
370
  refute_validates(obj, :acceptance, attribute, opts, msg)
371
371
  end
372
372
  alias_method :refute_validates_acceptance_of, :refute_validates_acceptance
373
-
373
+
374
374
  # Test for validating the confirmation of a model's attribute.
375
- #
375
+ #
376
376
  # it { refute_validates_confirmation(User.new, :password, { message: '...' }) }
377
377
  # it { User.new.must_validate_confirmation_of(:password, { message: '...' }) }
378
- #
378
+ #
379
379
  def refute_validates_confirmation(obj, attribute, opts = {}, msg = nil)
380
380
  refute_validates(obj, :confirmation, attribute, opts, msg)
381
381
  end
382
382
  alias_method :refute_validates_confirmation_of, :refute_validates_confirmation
383
-
383
+
384
384
  # Base test for validations of a model, used mainly as a shortcut for other assertions
385
- def refute_validates(obj, validation_type, attribute, opts = {}, msg = nil, &blk)
386
- msg = msg.nil? ? '' : "#{msg}\n"
387
- err_msg = []
388
- conf_msg = []
385
+ def refute_validates(obj, validation_type, attribute, opts = {}, msg = nil)
386
+ msg = msg.nil? ? "" : "#{msg}\n"
389
387
  unless obj.respond_to?(attribute)
390
- assert(false, "Column :#{attribute} is not defined in #{obj.class.to_s}, so cannot be validated")
388
+ assert(false, "Column :#{attribute} is not defined in #{obj.class}, so cannot be validated")
391
389
  end
392
-
393
390
  msg << "Expected #{obj.class} NOT to validate :#{attribute} with :#{validation_type}"
394
-
395
391
  if _validated_model?(obj)
396
-
397
392
  if _validated_column?(obj, attribute)
398
393
  msg << ", but the column :#{attribute} was validated with :#{validation_type}"
399
394
  assert(false, msg)
@@ -401,65 +396,73 @@ module Minitest::Assertions
401
396
  assert(true, msg)
402
397
  end
403
398
  else
404
- assert(false, "No validations defined in #{obj.class.to_s}")
399
+ assert(false, "No validations defined in #{obj.class}")
405
400
  end
406
401
  end
407
-
408
-
409
- #
402
+
403
+ #
410
404
  def assert_raises_validation_failed(obj)
411
405
  assert_raises(::Sequel::ValidationFailed) { obj.save }
412
406
  end
413
407
  alias_method :assert_fails_validation, :assert_raises_validation_failed
414
-
415
-
408
+
409
+ # #
410
+ # #
411
+ # def assert_presence(obj, attr, value)
412
+ # obj.send("#{attr}=", value)
413
+ # assert(obj.valid?)
414
+ # end
415
+ #
416
+ # [nil, '', ' '].each { |x| }
417
+ #
418
+ # end
419
+
416
420
  private
417
-
418
-
419
- #
421
+
422
+ #
420
423
  def _validated_model?(model)
421
- return (model.class.respond_to?(:has_validations?) && model.class.has_validations?)
424
+ (model.class.respond_to?(:has_validations?) && model.class.has_validations?)
422
425
  end
423
-
424
- #
426
+
427
+ #
425
428
  def _validated_column?(model, attribute)
426
429
  return false unless _validated_model?(model)
427
- return model.class.validation_reflections.keys.include?(attribute.to_sym)
430
+ model.class.validation_reflections.keys.include?(attribute.to_sym)
428
431
  end
429
-
430
- #
432
+
433
+ #
431
434
  def _validated_with_validation_type?(model, attribute, validation_type)
432
435
  return false unless _validated_column?(model, attribute)
433
- return _validation_types_hash_for_column(model, attribute).keys.include?(validation_type)
436
+ _validation_types_hash_for_column(model, attribute).keys.include?(validation_type)
434
437
  end
435
-
436
- #
438
+
439
+ #
437
440
  def _validation_types_hash_for_column(model, attribute)
438
441
  h = {}
439
442
  model.class.validation_reflections[attribute].each { |c| h[c[0]] = c[1] }
440
443
  h
441
444
  end
442
-
443
- #
445
+
446
+ #
444
447
  def _available_validation_types
445
448
  [:format, :length, :presence, :numericality, :confirmation, :acceptance, :inclusion, :uniqueness]
446
449
  end
447
-
448
- #
450
+
451
+ #
449
452
  def _available_validation_options
450
453
  [
451
454
  :message, :if, :is, :in, :allow_blank, :allow_missing, :allow_nil, :accept, :with, :within,
452
455
  :only_integer, :maximum, :minimum, :nil_message, :too_long, :too_short, :wrong_length
453
456
  ]
454
457
  end
455
-
456
- #
458
+
459
+ #
457
460
  def _valid_validation_options(type = nil)
458
461
  arr = [:message]
459
462
  case type.to_sym
460
463
  when :each
461
464
  # validates_each (*atts, &block)
462
- # Adds a validation for each of the given attributes using the supplied block.
465
+ # Adds a validation for each of the given attributes using the supplied block.
463
466
  [:allow_blank, :allow_missing, :allow_nil].each { |a| arr << a }
464
467
  when :acceptance
465
468
  # The value required for the object to be valid (default: '1')
@@ -474,76 +477,73 @@ module Minitest::Assertions
474
477
  # Whether only integers are valid values (default: false)
475
478
  arr << :only_integer
476
479
  when :length
477
- #
478
- # :message :: The message to use (no default, overrides :nil_message, :too_long,
480
+ #
481
+ # :message :: The message to use (no default, overrides :nil_message, :too_long,
479
482
  # :too_short, and :wrong_length options if present)
480
- #
481
- # :nil_message :: The message to use use if :maximum option is used and the value is nil
483
+ #
484
+ # :nil_message :: The message to use use if :maximum option is used and the value is nil
482
485
  # (default: 'is not present')
483
- #
486
+ #
484
487
  # :too_long :: The message to use use if it the value is too long (default: 'is too long')
485
- #
486
- # :too_short :: The message to use use if it the value is too short
488
+ #
489
+ # :too_short :: The message to use use if it the value is too short
487
490
  # (default: 'is too short')
488
- #
489
- # :wrong_length :: The message to use use if it the value is not valid
491
+ #
492
+ # :wrong_length :: The message to use use if it the value is not valid
490
493
  # (default: 'is the wrong length')
491
- #
494
+ #
492
495
  # SIZE
493
496
  # :is :: The exact size required for the value to be valid (no default)
494
497
  # :minimum :: The minimum size allowed for the value (no default)
495
498
  # :maximum :: The maximum size allowed for the value (no default)
496
- # :within :: The array/range that must include the size of the value for it to be valid
499
+ # :within :: The array/range that must include the size of the value for it to be valid
497
500
  # (no default)
498
-
499
- [ :is, :maximum, :minimum, :nil_message, :too_long, :too_short, :within, :wrong_length ]
500
- .each { |a| arr << a }
501
+
502
+ [:is, :maximum, :minimum, :nil_message, :too_long, :too_short, :within, :wrong_length].each { |a| arr << a }
501
503
  else
502
504
  arr
503
505
  end unless type.nil?
504
506
  arr
505
507
  end
506
-
507
- end
508
508
 
509
+ end
509
510
 
510
511
  # add support for Spec syntax
511
512
  module Minitest::Expectations
512
513
  infect_an_assertion :assert_validates, :must_validate, :reverse
513
514
  infect_an_assertion :assert_validates_presence, :must_validate_presence_of, :reverse
514
515
  infect_an_assertion :assert_validates_format, :must_validate_format_of, :reverse
515
-
516
+
516
517
  infect_an_assertion :assert_validates_length, :must_validate_length_of, :reverse
517
518
  infect_an_assertion :assert_validates_exact_length, :must_validate_exact_length_of, :reverse
518
519
  infect_an_assertion :assert_validates_min_length, :must_validate_min_length_of, :reverse
519
520
  infect_an_assertion :assert_validates_max_length, :must_validate_max_length_of, :reverse
520
521
  infect_an_assertion :assert_validates_length_range, :must_validate_length_range_of, :reverse
521
-
522
+
522
523
  infect_an_assertion :assert_validates_integer, :must_validate_integer_of, :reverse
523
524
  infect_an_assertion :assert_validates_numericality, :must_validate_numericality_of, :reverse
524
525
  infect_an_assertion :assert_validates_confirmation, :must_validate_confirmation_of, :reverse
525
526
  infect_an_assertion :assert_validates_acceptance, :must_validate_acceptance_of, :reverse
526
527
  infect_an_assertion :assert_validates_inclusion, :must_validate_inclusion_of, :reverse
527
528
  infect_an_assertion :assert_validates_uniqueness, :must_validate_uniqueness_of, :reverse
528
-
529
+
529
530
  infect_an_assertion :assert_fails_validation, :must_fail_validation, :reverse
530
-
531
-
531
+
532
+
532
533
  infect_an_assertion :refute_validates, :wont_validate, :reverse
533
534
  infect_an_assertion :refute_validates_presence, :wont_validate_presence_of, :reverse
534
535
  infect_an_assertion :refute_validates_format, :wont_validate_format_of, :reverse
535
-
536
+
536
537
  infect_an_assertion :refute_validates_length, :wont_validate_length_of, :reverse
537
538
  infect_an_assertion :refute_validates_exact_length, :wont_validate_exact_length_of, :reverse
538
539
  infect_an_assertion :refute_validates_min_length, :wont_validate_min_length_of, :reverse
539
540
  infect_an_assertion :refute_validates_max_length, :wont_validate_max_length_of, :reverse
540
541
  infect_an_assertion :refute_validates_length_range, :wont_validate_length_range_of, :reverse
541
-
542
+
542
543
  infect_an_assertion :refute_validates_integer, :wont_validate_integer_of, :reverse
543
544
  infect_an_assertion :refute_validates_numericality, :wont_validate_numericality_of, :reverse
544
545
  infect_an_assertion :refute_validates_confirmation, :wont_validate_confirmation_of, :reverse
545
546
  infect_an_assertion :refute_validates_acceptance, :wont_validate_acceptance_of, :reverse
546
547
  infect_an_assertion :refute_validates_inclusion, :wont_validate_inclusion_of, :reverse
547
548
  infect_an_assertion :refute_validates_uniqueness, :wont_validate_uniqueness_of, :reverse
548
-
549
549
  end