minitest-sequel 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.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
|