minitest-sequel 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +24 -0
- data/.github/workflows/ruby.yml +45 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +48 -0
- data/.rubocop_todo.yml +7 -0
- data/CODE_OF_CONDUCT.md +17 -10
- data/Gemfile +81 -2
- data/Guardfile +26 -0
- data/README.md +368 -243
- data/Rakefile +16 -24
- data/lib/minitest/sequel/associations.rb +353 -163
- data/lib/minitest/sequel/columns.rb +204 -140
- data/lib/minitest/sequel/helpers.rb +190 -21
- data/lib/minitest/sequel/plugins.rb +409 -129
- data/lib/minitest/sequel/validations.rb +1122 -504
- data/lib/minitest/sequel/version.rb +4 -3
- data/lib/minitest/sequel.rb +27 -23
- data/minitest-sequel.gemspec +28 -27
- metadata +49 -143
@@ -1,166 +1,446 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'minitest/spec'
|
2
4
|
|
3
5
|
# reopening to add validations functionality
|
4
|
-
module Minitest
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
|
27
|
-
|
6
|
+
module Minitest
|
7
|
+
# add support for Assert syntax
|
8
|
+
module Assertions
|
9
|
+
# Test if a model instance is timestamped via .plugin(:timestamps)
|
10
|
+
#
|
11
|
+
# This assertion checks if a given model instance has been properly timestamped
|
12
|
+
# using the Sequel Timestamps plugin. It verifies the presence of the plugin,
|
13
|
+
# the existence of the required columns, and the correct behavior of timestamps
|
14
|
+
# for both new and updated records.
|
15
|
+
#
|
16
|
+
# @param model [Sequel::Model] The model instance to test
|
17
|
+
# @param opts [Hash] Options to modify the assertion behavior
|
18
|
+
# @option opts [Boolean] :updated_record Set to true to test an updated record
|
19
|
+
#
|
20
|
+
# @example Testing a new record
|
21
|
+
# let(:m) { Post.create(title: 'Dummy') }
|
22
|
+
# assert_no_error { assert_timestamped_model_instance(m) }
|
23
|
+
#
|
24
|
+
# @example Testing an updated record
|
25
|
+
# m.title = 'Updated'
|
26
|
+
# m.save
|
27
|
+
# assert_no_error { assert_timestamped_model_instance(m, updated_record: true) }
|
28
|
+
#
|
29
|
+
# @example Testing an incorrectly timestamped record
|
30
|
+
# let(:m) { Post.create(title: 'Dummy', updated_at: Time.now) }
|
31
|
+
#
|
32
|
+
# msg = /expected #.updated_at to be NIL on new record/
|
33
|
+
#
|
34
|
+
# assert_error_raised(msg) do
|
35
|
+
# assert_timestamped_model_instance(m, updated_record: false)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @raise [Minitest::Assertion] If the model instance does not meet the timestamped criteria
|
39
|
+
#
|
40
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
41
|
+
def assert_timestamped_model_instance(model, opts = {})
|
42
|
+
model_class = model.class
|
43
|
+
|
44
|
+
# 1. test for Timestamps plugin
|
45
|
+
plugs = model_class.instance_variable_get(:@plugins).map(&:to_s)
|
46
|
+
|
47
|
+
unless plugs.include?('Sequel::Plugins::Timestamps')
|
48
|
+
msg = "Not a plugin(:timestamps) model, available plugins are: #{plugs.inspect}"
|
49
|
+
raise(Minitest::Assertion, msg)
|
50
|
+
end
|
51
|
+
|
52
|
+
str = 'AssertTimestampedModelInstance -'
|
53
|
+
|
28
54
|
# 2. test for created_at / :updated_at columns
|
29
|
-
|
30
|
-
assert_have_column(model, :
|
55
|
+
msg = "#{str} expected model to have column :created_at. Debug: [#{model.inspect}]"
|
56
|
+
assert_have_column(model, :created_at, {}, msg)
|
57
|
+
|
58
|
+
msg = "#{str} expected model to have column :updated_at. Debug: [#{model.inspect}]"
|
59
|
+
assert_have_column(model, :updated_at, {}, msg)
|
31
60
|
|
32
61
|
if opts[:updated_record]
|
33
62
|
# 4. updated record
|
34
|
-
|
35
|
-
assert_instance_of(Time, model.
|
63
|
+
msg = "#{str} expected #created_at to be an instance of Time on updated record"
|
64
|
+
assert_instance_of(Time, model.created_at, msg)
|
65
|
+
|
66
|
+
msg = "#{str} expected #updated_at to be an instance of Time on updated record"
|
67
|
+
assert_instance_of(Time, model.updated_at, msg)
|
36
68
|
else
|
37
69
|
# 3. initial record
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
}
|
70
|
+
msg = "#{str} expected #created_at to be an instance of Time on new record"
|
71
|
+
assert_instance_of(Time, model.created_at, msg)
|
72
|
+
|
73
|
+
msg = "#{str} expected #updated_at to be NIL on new record"
|
74
|
+
assert_no_error { assert_nil(model.updated_at, msg) }
|
42
75
|
end
|
43
|
-
else
|
44
|
-
raise(Minitest::Assertion, "Not a plugin(:timestamps) model, available plugins are: #{plugs.inspect}")
|
45
76
|
end
|
46
|
-
|
77
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
78
|
+
|
79
|
+
# Test if a model class is timestamped with .plugin(:timestamps)
|
80
|
+
#
|
81
|
+
# This assertion checks if a given model class has been properly configured
|
82
|
+
# with the Sequel Timestamps plugin. It verifies the presence of the plugin,
|
83
|
+
# the existence of the required columns, and the correct behavior of timestamps
|
84
|
+
# for both new and updated records.
|
85
|
+
#
|
86
|
+
# @param model [Class] The model class to test
|
87
|
+
# @param opts [Hash] Options to modify the assertion behavior
|
88
|
+
#
|
89
|
+
# @example Testing a timestamped model
|
90
|
+
# class Comment < Sequel::Model
|
91
|
+
# plugin(:timestamps)
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# assert_no_error { assert_timestamped_model(Comment) }
|
95
|
+
#
|
96
|
+
# @example Testing a non-timestamped model
|
97
|
+
# class Post < Sequel::Model; end
|
98
|
+
#
|
99
|
+
# msg = /Not a \.plugin\(:timestamps\) model, available plugins are/
|
100
|
+
#
|
101
|
+
# assert_error_raised(msg) { assert_timestamped_model(Post) }
|
102
|
+
#
|
103
|
+
# @example Testing with additional attributes to create a valid model instance
|
104
|
+
# assert_no_error do
|
105
|
+
# assert_timestamped_model(Comment, {body: "I think...", email: "e@email.com"})
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# @raise [Minitest::Assertion] If the model class does not meet the timestamped criteria
|
109
|
+
#
|
110
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
111
|
+
def assert_timestamped_model(model, opts = {})
|
112
|
+
m = opts.empty? ? model.send(:make) : model.send(:create, opts)
|
113
|
+
|
114
|
+
# 1. test for Timestamps plugin
|
115
|
+
plugs = model.instance_variable_get(:@plugins).map(&:to_s)
|
116
|
+
|
117
|
+
unless plugs.include?('Sequel::Plugins::Timestamps')
|
118
|
+
msg = "Not a plugin(:timestamps) model, available plugins are: #{plugs.inspect}"
|
119
|
+
raise(Minitest::Assertion, msg)
|
120
|
+
end
|
121
|
+
|
122
|
+
str = 'AssertTimestampedModel - expected'
|
47
123
|
|
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
124
|
# 2. test for created_at / :updated_at columns
|
74
|
-
|
75
|
-
assert_have_column(m, :
|
125
|
+
msg = "#{str} model to have column :created_at. Debug: [#{m.inspect}]"
|
126
|
+
assert_have_column(m, :created_at, {}, msg)
|
127
|
+
|
128
|
+
msg = "#{str} model to have column :updated_at. Debug: [#{m.inspect}]"
|
129
|
+
assert_have_column(m, :updated_at, {}, msg)
|
76
130
|
|
77
131
|
# 3. initial record
|
78
|
-
|
79
|
-
assert_instance_of(
|
132
|
+
msg = "#{str} :created_at to be an instance of Time on new record. Debug: [#{m.inspect}]"
|
133
|
+
assert_instance_of(Time, m.created_at, msg)
|
134
|
+
|
135
|
+
msg = "#{str} :updated_at to be an instance of Time on new record. Debug: [#{m.inspect}]"
|
136
|
+
assert_instance_of(NilClass, m.updated_at, msg)
|
80
137
|
|
81
138
|
# 4. updated record
|
82
139
|
# old_ts = m.created_at
|
83
140
|
# sleep 1 # TODO: could this be converted to timecop or similar?
|
84
|
-
m.title = "#{m.title} updated"
|
141
|
+
# m.title = "#{m.title} updated"
|
85
142
|
assert(m.save, "AssertTimestampedModel:#save - updated model failed. Debug: [#{m.inspect}]")
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
143
|
+
|
144
|
+
msg = "#{str} :created_at to be an instance of Time on updated record. Debug: [#{m.inspect}]"
|
145
|
+
assert_instance_of(Time, m.created_at, msg)
|
146
|
+
|
147
|
+
msg = "#{str} :updated_at to be an instance of Time on updated record. Debug: [#{m.inspect}]"
|
148
|
+
assert_instance_of(Time, m.updated_at, msg)
|
149
|
+
|
150
|
+
# assert_equal(old_ts, m.created_at, "#{str} the :created_at timestamp to be unchanged")
|
91
151
|
end
|
92
|
-
|
152
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
153
|
+
|
154
|
+
# Test if a model class is paranoid with .plugin(:paranoid) via [Sequel-Paranoid](https://github.com/sdepold/sequel-paranoid)
|
155
|
+
#
|
156
|
+
# This assertion checks if a given model class has been properly configured
|
157
|
+
# with the Sequel Paranoid plugin. It verifies the presence of the plugin,
|
158
|
+
# the existence of the required column (:deleted_at), and the correct behavior
|
159
|
+
# of soft deletion for both new and updated records.
|
160
|
+
#
|
161
|
+
# @param model [Class] The model class to test
|
162
|
+
# @param opts [Hash] Options to modify the assertion behavior
|
163
|
+
#
|
164
|
+
# @example Testing a paranoid model
|
165
|
+
# class Comment < Sequel::Model
|
166
|
+
# plugin(:paranoid)
|
167
|
+
# end
|
168
|
+
# assert_no_error { assert_paranoid_model(Comment) }
|
169
|
+
#
|
170
|
+
# @example Testing a non-paranoid model
|
171
|
+
# class Post < Sequel::Model; end
|
172
|
+
#
|
173
|
+
# msg = /Not a plugin\(:paranoid\) model, available plugins are/
|
174
|
+
#
|
175
|
+
# assert_error_raised(msg) { assert_paranoid_model(Post) }
|
176
|
+
#
|
177
|
+
# @example Testing with additional attributes to create a valid model instance
|
178
|
+
# assert_no_error do
|
179
|
+
# assert_paranoid_model(Comment, {body: "I think...", email: "e@email.com"})
|
180
|
+
# end
|
181
|
+
#
|
182
|
+
# @raise [Minitest::Assertion] If the model class does not meet the paranoid criteria
|
183
|
+
#
|
184
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
185
|
+
def assert_paranoid_model(model, opts = {})
|
186
|
+
m = opts.empty? ? model.send(:make) : model.send(:create, opts)
|
187
|
+
|
188
|
+
# 1. test for Paranoid plugin
|
189
|
+
plugs = model.instance_variable_get(:@plugins).map(&:to_s)
|
190
|
+
|
191
|
+
unless plugs.include?('Sequel::Plugins::Paranoid')
|
192
|
+
raise(
|
193
|
+
Minitest::Assertion,
|
194
|
+
"Not a plugin(:paranoid) model, available plugins are: #{plugs.inspect}"
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
198
|
+
str = 'AssertParanoidModel - expected'
|
199
|
+
|
200
|
+
msg = "#{str} #deleted_at to be NIL on new model"
|
201
|
+
assert_nil(m.deleted_at, msg)
|
93
202
|
|
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
203
|
# after update
|
121
204
|
assert(m.save, "AssertParanoidModel:save - updated model failed. Debug: [#{m.inspect}]")
|
122
|
-
|
205
|
+
|
206
|
+
msg = "#{str} #deleted_at to be NIL on updated model"
|
207
|
+
assert_nil(m.deleted_at, msg)
|
208
|
+
|
123
209
|
# after destroy
|
124
210
|
assert(m.destroy, "AssertParanoidModel:destroy - destroy model failed. Debug: [#{m.inspect}]")
|
125
|
-
|
126
|
-
|
127
|
-
|
211
|
+
|
212
|
+
# assert_instance_of(Time, m.deleted_at,
|
213
|
+
#
|
214
|
+
msg = "#{str} #deleted_at to be instance of Time on destroyed model, Debug: [#{m.inspect}]"
|
215
|
+
assert_instance_of(NilClass, m.deleted_at, msg)
|
216
|
+
end
|
217
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
218
|
+
|
219
|
+
# Test to ensure the current model is NOT a :timestamped model
|
220
|
+
#
|
221
|
+
# This assertion checks if a given model class has NOT been configured
|
222
|
+
# with the Sequel Timestamps plugin. It verifies the absence of the plugin
|
223
|
+
# in the model's list of plugins.
|
224
|
+
#
|
225
|
+
# @param model [Class] The model class to test
|
226
|
+
# @param _opts [Hash] Unused options parameter (kept for consistency with other methods)
|
227
|
+
#
|
228
|
+
# @example Testing a non-timestamped model
|
229
|
+
# class Post < Sequel::Model; end
|
230
|
+
# it { refute_timestamped_model(Post) }
|
231
|
+
#
|
232
|
+
# @example Testing a timestamped model (will fail)
|
233
|
+
# class Comment < Sequel::Model
|
234
|
+
# plugin :timestamps
|
235
|
+
# end
|
236
|
+
# it { refute_timestamped_model(Comment) } # This will fail
|
237
|
+
#
|
238
|
+
# @raise [Minitest::Assertion] If the model class is configured with the Timestamps plugin
|
239
|
+
#
|
240
|
+
def refute_timestamped_model(model, _opts = {})
|
241
|
+
plugs = model.instance_variable_get(:@plugins).map(&:to_s)
|
242
|
+
|
243
|
+
msg = "RefuteTimestampedModel - expected #{model} to NOT be a :timestamps model, but it was."
|
244
|
+
msg << " Debug: [#{plugs.inspect}]"
|
245
|
+
|
246
|
+
refute_includes(plugs, 'Sequel::Plugins::Timestamps', msg)
|
247
|
+
end
|
248
|
+
|
249
|
+
# Test to ensure the current model is NOT a :paranoid model
|
250
|
+
#
|
251
|
+
# This assertion checks if a given model class has NOT been configured
|
252
|
+
# with the Sequel Paranoid plugin. It verifies the absence of the plugin
|
253
|
+
# in the model's list of plugins.
|
254
|
+
#
|
255
|
+
# @param model [Class] The model class to test
|
256
|
+
#
|
257
|
+
# @example Testing a non-paranoid model
|
258
|
+
# class Post < Sequel::Model; end
|
259
|
+
# it { refute_paranoid_model(Post) }
|
260
|
+
#
|
261
|
+
# @example Testing a paranoid model (will fail)
|
262
|
+
# class Comment < Sequel::Model
|
263
|
+
# plugin :paranoid
|
264
|
+
# end
|
265
|
+
# it { refute_paranoid_model(Comment) } # This will fail
|
266
|
+
#
|
267
|
+
# @raise [Minitest::Assertion] If the model class is configured with the Paranoid plugin
|
268
|
+
#
|
269
|
+
def refute_paranoid_model(model)
|
270
|
+
plugs = model.instance_variable_get(:@plugins).map(&:to_s)
|
271
|
+
|
272
|
+
msg = "RefuteParanoidModel - expected #{model} to NOT be a :paranoid model, but it was. "
|
273
|
+
msg << "Debug: [#{plugs.inspect}]"
|
274
|
+
|
275
|
+
refute_includes(plugs, 'Sequel::Plugins::Paranoid', msg)
|
128
276
|
end
|
129
277
|
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
278
|
+
# /module Assertions
|
279
|
+
|
280
|
+
# add support for Spec syntax
|
281
|
+
module Expectations
|
282
|
+
infect_an_assertion :assert_timestamped_model, :must_be_timestamped_model, :reverse
|
283
|
+
infect_an_assertion :assert_timestamped_model, :must_be_a_timestamped_model, :reverse
|
284
|
+
infect_an_assertion :assert_paranoid_model, :must_be_paranoid_model, :reverse
|
285
|
+
infect_an_assertion :assert_paranoid_model, :must_be_a_paranoid_model, :reverse
|
286
|
+
|
287
|
+
infect_an_assertion :refute_timestamped_model, :wont_be_timestamped_model, :reverse
|
288
|
+
infect_an_assertion :refute_timestamped_model, :wont_be_a_timestamped_model, :reverse
|
289
|
+
infect_an_assertion :refute_paranoid_model, :wont_be_paranoid_model, :reverse
|
290
|
+
infect_an_assertion :refute_paranoid_model, :wont_be_a_paranoid_model, :reverse
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# reopening the class
|
295
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
296
|
+
class Minitest::Spec < Minitest::Test
|
297
|
+
# Ensure that a given model is properly configured as a paranoid model
|
134
298
|
#
|
135
|
-
#
|
299
|
+
# This method sets up a series of tests to verify that a model
|
300
|
+
# is correctly using the Sequel Paranoid plugin. It checks the behavior
|
301
|
+
# of the :deleted_at column in various scenarios.
|
136
302
|
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
#
|
303
|
+
# @param model [Class] The model class to test
|
304
|
+
#
|
305
|
+
# @example Testing a paranoid model
|
306
|
+
# class Comment < Sequel::Model
|
307
|
+
# plugin :paranoid
|
308
|
+
# end
|
143
309
|
#
|
144
|
-
#
|
310
|
+
# describe Comment do
|
311
|
+
# ensure_paranoid_model(Comment)
|
312
|
+
# end
|
145
313
|
#
|
146
|
-
|
147
|
-
|
148
|
-
|
314
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
315
|
+
def self.ensure_paranoid_model(model)
|
316
|
+
# rubocop:disable Metrics/BlockLength
|
317
|
+
describe 'a paranoid model with .plugin(:paranoid)' do
|
318
|
+
let(:m) { model.send(:make) }
|
319
|
+
|
320
|
+
describe 'on a new record' do
|
321
|
+
it '#:deleted_at should be NULL (empty)' do
|
322
|
+
msg = 'EnsureParanoidModel#new - expected #deleted_at to be nil on new record. '
|
323
|
+
msg << "Debug: [#{m.inspect}]"
|
324
|
+
|
325
|
+
assert_nil(m.deleted_at, msg)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
describe 'on an updated record' do
|
330
|
+
it '#:deleted_at should be NULL (empty)' do
|
331
|
+
m.save
|
332
|
+
|
333
|
+
msg = 'EnsureParanoidModel#update - expected #deleted_at to be nil on updated record. '
|
334
|
+
msg << "Debug: [#{m.inspect}]"
|
335
|
+
|
336
|
+
assert_nil(m.deleted_at, msg)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
describe 'after a record#destroy' do
|
341
|
+
it "#:deleted_at should be NULL (empty) on a delete'd record" do
|
342
|
+
m.destroy
|
343
|
+
|
344
|
+
msg = 'EnsureParanoidModel#destroy - expected #deleted_at to be nil on destroyed record. '
|
345
|
+
msg << "Debug: [#{m.inspect}]"
|
346
|
+
|
347
|
+
assert_nil(m.deleted_at, msg)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe 'after a record#delete' do
|
352
|
+
it "#:deleted_at should be NULL (empty) on a delete'd record" do
|
353
|
+
m.delete
|
354
|
+
|
355
|
+
msg = 'EnsureParanoidModel#delete - expected #deleted_at to be nil on deleted record. '
|
356
|
+
msg << "Debug: [#{m.inspect}]"
|
357
|
+
|
358
|
+
assert_nil(m.deleted_at, msg)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe 'after a record#soft_delete' do
|
363
|
+
it '#:deleted_at should be a timestamp' do
|
364
|
+
refute(m.deleted?)
|
365
|
+
assert_no_error { m.soft_delete }
|
366
|
+
assert(m.deleted?)
|
367
|
+
|
368
|
+
msg = 'EnsureParanoidModel#destroy - expected #deleted_at to be instance of Time '
|
369
|
+
msg << "on deleted model. Debug: [#{m.inspect}]"
|
370
|
+
|
371
|
+
assert_instance_of(Time, m.deleted_at, msg)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
# rubocop:enable Metrics/BlockLength
|
149
376
|
end
|
150
|
-
|
151
|
-
|
152
|
-
|
377
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
378
|
+
|
379
|
+
# Ensure that a given model is properly configured as a timestamped model
|
380
|
+
#
|
381
|
+
# This method sets up a series of tests to verify that a model
|
382
|
+
# is correctly using the aequel-timestamps plugin. It checks the behavior
|
383
|
+
# of the :created_at and :updated_at columns in various scenarios.
|
384
|
+
#
|
385
|
+
# @param model [Class] The model class to test
|
386
|
+
#
|
387
|
+
# @example Testing a timestamped model
|
388
|
+
# class Comment < Sequel::Model
|
389
|
+
# plugin :timestamps
|
390
|
+
# end
|
391
|
+
#
|
392
|
+
# describe Comment do
|
393
|
+
# ensure_timestamped_model(Comment)
|
394
|
+
# end
|
395
|
+
#
|
396
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
397
|
+
def self.ensure_timestamped_model(model)
|
398
|
+
# rubocop:disable Metrics/BlockLength
|
399
|
+
describe 'a timestamped model with .plugin(:timestamps)' do
|
400
|
+
let(:m) { model.send(:make) }
|
153
401
|
|
402
|
+
describe 'a new record' do
|
403
|
+
it '#:created_at should be a timestamp' do
|
404
|
+
msg = 'EnsureTimestampedModel#new - expected #created_at to be an instance of Time '
|
405
|
+
msg << "on new record. Debug: [#{m.inspect}]"
|
154
406
|
|
155
|
-
|
156
|
-
|
407
|
+
assert_instance_of(Time, m.created_at, msg)
|
408
|
+
end
|
157
409
|
|
158
|
-
|
159
|
-
|
160
|
-
|
410
|
+
it '#:updated_at should be nil (empty)' do
|
411
|
+
msg = 'EnsureTimestampedModel#new - expected #updated_at to be nil on new record. '
|
412
|
+
msg << "Debug: [#{m.inspect}]"
|
161
413
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
414
|
+
assert_nil(m.updated_at, msg)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
describe 'after an update' do
|
419
|
+
it '#:created_at should remain unchanged ' do
|
420
|
+
assert_instance_of(Time, m.created_at)
|
421
|
+
old_ts = m.created_at
|
422
|
+
|
423
|
+
sleep 1 # TODO: convert this with time_cop or similar one day.
|
424
|
+
m.save
|
425
|
+
|
426
|
+
msg = 'EnsureTimestampedModel#update - expected #created_at to be unchanged '
|
427
|
+
msg << "on update record. Debug: [#{m.inspect}]"
|
428
|
+
|
429
|
+
assert_equal(old_ts, m.created_at, msg)
|
430
|
+
end
|
431
|
+
|
432
|
+
it '#:updated_at should be a timestamp' do
|
433
|
+
m.save
|
434
|
+
|
435
|
+
msg = 'EnsureTimestampedModel#new - expected #updated_at to be an instance of Time '
|
436
|
+
msg << "on updated record. Debug: [#{m.inspect}]"
|
437
|
+
|
438
|
+
assert_instance_of(Time, m.updated_at, msg)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
# rubocop:enable Metrics/BlockLength
|
443
|
+
end
|
444
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
166
445
|
end
|
446
|
+
# rubocop:enable Style/ClassAndModuleChildren
|