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
data/README.md
CHANGED
@@ -1,19 +1,26 @@
|
|
1
|
+
<!-- markdownlint-disable MD013 MD033 -->
|
2
|
+
|
1
3
|
# Minitest-Sequel
|
2
4
|
|
3
|
-
[
|
4
|
-
|
5
|
+
[](https://github.com/kematzy/minitest-sequel/actions/workflows/ruby.yml) - [](https://badge.fury.io/rb/minitest-sequel) - [](https://github.com/rubocop/rubocop-minitest)
|
6
|
+
|
7
|
+
Coverage: Currently at **99.1%**
|
8
|
+
|
9
|
+
[Minitest](https://github.com/seattlerb/minitest) assertions to speed-up development and testing
|
10
|
+
of [Sequel](http://sequel.jeremyevans.net/) database setups.
|
5
11
|
|
6
|
-
The general hope is that this gem will contain a variety of useful assertions in all areas of
|
7
|
-
code within your apps, gems, etc.
|
12
|
+
The general hope is that this gem will contain a variety of useful assertions in all areas of
|
13
|
+
testing Sequel database code within your apps, gems, etc.
|
8
14
|
|
9
15
|
Please help out with missing features / functionality.
|
10
16
|
|
11
|
-
|
17
|
+
---
|
12
18
|
|
13
19
|
## Model Definitions
|
14
20
|
|
21
|
+
### `#assert_have_column (:model, :attribute, :opts, :msg)`
|
15
22
|
|
16
|
-
|
23
|
+
spec: `_(model).must_have_column(:attribute, :opts, :msg)`
|
17
24
|
|
18
25
|
Conveniently test your Model definitions as follows:
|
19
26
|
|
@@ -22,9 +29,9 @@ let(:m) { Post.first }
|
|
22
29
|
|
23
30
|
it { assert_have_column(m, :title, type: :string, db_type: 'varchar(250)', allow_null: :false) }
|
24
31
|
|
25
|
-
it { m.must_have_column(:title, type: :string, allow_null: :false) }
|
32
|
+
it { _(m).must_have_column(:title, type: :string, allow_null: :false) }
|
26
33
|
|
27
|
-
it { m.must_have_column(:title, { type: :string, allow_null: :false }, "Custom messsage
|
34
|
+
it { _(m).must_have_column(:title, { type: :string, allow_null: :false }, "Custom messsage") }
|
28
35
|
|
29
36
|
# definition of args
|
30
37
|
# assert_have_column(
|
@@ -35,81 +42,72 @@ it { m.must_have_column(:title, { type: :string, allow_null: :false }, "Custom m
|
|
35
42
|
# )
|
36
43
|
```
|
37
44
|
|
38
|
-
The
|
39
|
-
|
45
|
+
The `#assert_have_column()` method first tests if the column name is defined in the Model and then
|
46
|
+
checks all passed options.
|
40
47
|
|
41
48
|
The following options are valid and checked:
|
42
49
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
- `:type`
|
51
|
+
- `:db_type`
|
52
|
+
- `:allow_null`
|
53
|
+
- `:max_length`
|
54
|
+
- `:default`
|
55
|
+
- `:primary_key`
|
56
|
+
- `:auto_increment`
|
51
57
|
|
52
|
-
In the event the specs differ from the actual database implementation an extensive error message
|
53
|
-
differing option(s) is provided to help speed up debugging the issue:
|
58
|
+
In the event the specs differ from the actual database implementation an extensive error message
|
59
|
+
with the differing option(s) is provided to help speed up debugging the issue:
|
54
60
|
|
55
|
-
```
|
61
|
+
```bash
|
56
62
|
Expected Post model to have column: :title with: \
|
57
|
-
{
|
63
|
+
{
|
64
|
+
type: 'string',
|
65
|
+
db_type: 'varchar(250)',
|
66
|
+
allow_null: 'false'
|
67
|
+
}
|
58
68
|
but found: { db_type: 'varchar(255)' }
|
59
69
|
```
|
60
70
|
|
61
|
-
|
71
|
+
> [!NOTE]
|
72
|
+
> To test options with a value that is either `nil`, `true` or `false`, please use `:nil`, `:false`
|
73
|
+
> or `:true` and provide numbers as 'strings' instead, ie: `'1'` instead of `1`.
|
62
74
|
|
63
|
-
To test options with a value that is either `nil`, `true` or `false`, please use `:nil`, `:false` or `:true` and provide
|
64
|
-
numbers as 'strings' instead, ie: `'1'` instead of `1`.
|
65
|
-
|
66
|
-
|
67
|
-
<br>
|
68
75
|
<br>
|
69
76
|
|
70
|
-
|
77
|
+
---
|
71
78
|
|
72
79
|
<br>
|
73
80
|
|
74
|
-
|
75
|
-
## Associations
|
81
|
+
## Model Associations
|
76
82
|
|
77
83
|
Conveniently test model associations quickly and easily with these Minitest assertions:
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
* `assert_association_many_to_many`
|
86
|
-
|
87
|
-
* `assert_association`
|
85
|
+
- `#assert_association_one_to_one`
|
86
|
+
- `#assert_association_one_to_many`
|
87
|
+
- `#assert_association_many_to_one`
|
88
|
+
- `#assert_association_many_to_many`
|
89
|
+
- `#assert_association`
|
88
90
|
|
89
91
|
<br>
|
90
|
-
<br>
|
91
|
-
|
92
92
|
|
93
93
|
### `:one_to_one` association
|
94
94
|
|
95
|
-
|
96
95
|
A model defined with an association like this:
|
97
96
|
|
98
|
-
|
99
97
|
```ruby
|
100
98
|
class Post < Sequel::Model
|
101
99
|
one_to_one :first_comment, class: :Comment, order: :id
|
102
100
|
end
|
103
101
|
```
|
104
102
|
|
105
|
-
Can be easily and quickly tested with
|
103
|
+
Can be easily and quickly tested with `#assert_association_one_to_one()` like this:
|
106
104
|
|
107
105
|
```ruby
|
108
106
|
let(:m) { Post.first }
|
109
107
|
|
110
108
|
it { assert_association_one_to_one(m, :first_comment)
|
111
109
|
# or
|
112
|
-
it { m.must_have_one_to_one_association(:first_comment) }
|
110
|
+
it { _(m).must_have_one_to_one_association(:first_comment) }
|
113
111
|
|
114
112
|
|
115
113
|
# definition of args
|
@@ -123,18 +121,28 @@ assert_association_one_to_one(
|
|
123
121
|
|
124
122
|
In the event of errors an extensive error message is provided:
|
125
123
|
|
126
|
-
```
|
124
|
+
```bash
|
127
125
|
# example error message
|
128
126
|
|
129
|
-
Expected Author to have a :one_to_one association :key_posts but no association \
|
130
|
-
|
131
|
-
{
|
132
|
-
|
127
|
+
Expected Author to have a :one_to_one association :key_posts but no association ':key_posts' \
|
128
|
+
was found - available associations are: [ \
|
129
|
+
{
|
130
|
+
:attribute=>:posts,
|
131
|
+
:type=>:one_to_many,
|
132
|
+
:class=>:Post,
|
133
|
+
:keys=>[:author_id]},
|
134
|
+
{
|
135
|
+
:attribute=>:key_post,
|
136
|
+
:type=>:one_to_one,
|
137
|
+
:class=>:Post,
|
138
|
+
:keys=>[:author_id]
|
139
|
+
}
|
133
140
|
]
|
134
141
|
```
|
135
142
|
|
136
143
|
<br>
|
137
|
-
|
144
|
+
|
145
|
+
---
|
138
146
|
|
139
147
|
### `:one_to_many` association
|
140
148
|
|
@@ -146,22 +154,23 @@ class Post < Sequel::Model
|
|
146
154
|
end
|
147
155
|
```
|
148
156
|
|
149
|
-
Can be easily and quickly tested with
|
157
|
+
Can be easily and quickly tested with `#assert_association_one_to_many()` like this:
|
150
158
|
|
151
159
|
```ruby
|
152
|
-
let(:
|
160
|
+
let(:m) { Post.first }
|
153
161
|
|
154
|
-
it { assert_association_one_to_many(
|
162
|
+
it { assert_association_one_to_many(m, :comments) }
|
155
163
|
# or
|
156
|
-
it { m.must_have_one_to_many_association(:comments) }
|
157
|
-
```
|
164
|
+
it { _(m).must_have_one_to_many_association(:comments) }
|
165
|
+
```
|
158
166
|
|
159
167
|
As above the assertion provides an extensive error message if something is wrong.
|
160
168
|
|
161
169
|
<br>
|
162
|
-
<br>
|
163
170
|
|
164
|
-
|
171
|
+
---
|
172
|
+
|
173
|
+
### `:many_to_one` association
|
165
174
|
|
166
175
|
A model defined with an association like this:
|
167
176
|
|
@@ -171,23 +180,23 @@ class Post < Sequel::Model
|
|
171
180
|
end
|
172
181
|
```
|
173
182
|
|
174
|
-
Can be easily and quickly tested with
|
183
|
+
Can be easily and quickly tested with `#assert_association_many_to_one()` like this:
|
175
184
|
|
176
185
|
```ruby
|
177
|
-
let(:
|
186
|
+
let(:m) { Post.first }
|
178
187
|
|
179
|
-
it { assert_association_many_to_one(
|
188
|
+
it { assert_association_many_to_one(m, :author) }
|
180
189
|
# or
|
181
|
-
it { m.must_have_many_to_one_association(:author) }
|
182
|
-
```
|
183
|
-
|
190
|
+
it { _(m).must_have_many_to_one_association(:author) }
|
191
|
+
```
|
184
192
|
|
185
193
|
As above the assertion provides an extensive error message if something is wrong.
|
186
194
|
|
187
195
|
<br>
|
188
|
-
<br>
|
189
196
|
|
190
|
-
|
197
|
+
---
|
198
|
+
|
199
|
+
### `:many_to_many` association
|
191
200
|
|
192
201
|
A model defined with an association like this:
|
193
202
|
|
@@ -197,47 +206,55 @@ class Post < Sequel::Model
|
|
197
206
|
end
|
198
207
|
```
|
199
208
|
|
200
|
-
Can be easily and quickly tested with
|
209
|
+
Can be easily and quickly tested with `#assert_association_many_to_many()` like this:
|
201
210
|
|
202
211
|
```ruby
|
203
|
-
let(:
|
212
|
+
let(:m) { Post.first }
|
204
213
|
|
205
|
-
it { assert_association_many_to_many(
|
214
|
+
it { assert_association_many_to_many(m, :categories) }
|
206
215
|
# or
|
207
|
-
it { m.must_have_many_to_many_association(:categories) }
|
208
|
-
```
|
216
|
+
it { _(m).must_have_many_to_many_association(:categories) }
|
217
|
+
```
|
209
218
|
|
210
219
|
If something is wrong an extensive error message is provided:
|
211
220
|
|
212
|
-
```
|
221
|
+
```bash
|
213
222
|
Expected Category to have a :many_to_many association :posts with given options: \
|
214
223
|
{:class_name=>'Posts'} but should be {:class_name=>'Post' }
|
215
224
|
```
|
216
225
|
|
217
226
|
or
|
218
227
|
|
219
|
-
```
|
220
|
-
Expected Category to have a :many_to_many association :post but no association \
|
221
|
-
|
222
|
-
{
|
223
|
-
:
|
228
|
+
```bash
|
229
|
+
Expected Category to have a :many_to_many association :post but no association ':post' was found \
|
230
|
+
- available associations are: [ \
|
231
|
+
{
|
232
|
+
:attribute=>:posts,
|
233
|
+
:type=>:many_to_many,
|
234
|
+
:class=>:Post,
|
235
|
+
:join_table=>:categories_posts,
|
236
|
+
:left_keys=>[:category_id],
|
237
|
+
:right_keys=>[:post_id]
|
224
238
|
}
|
225
239
|
]
|
226
240
|
```
|
227
241
|
|
228
242
|
<br>
|
229
|
-
<br>
|
230
243
|
|
231
|
-
|
232
|
-
|
244
|
+
---
|
245
|
+
|
246
|
+
### `#assert_association(:model, :type, :attribute, :options, :msg)`
|
247
|
+
|
248
|
+
spec: `_(model).must_have_association(:type, :attribute, :options, :msg)`
|
233
249
|
|
234
|
-
if the above assertion methods are insufficient, you can use the base
|
250
|
+
if the above assertion methods are insufficient, you can use the base
|
251
|
+
`assert_association` method instead.
|
235
252
|
|
236
253
|
```ruby
|
237
254
|
it "should have a :one_through_one association" do
|
238
255
|
assert_association(Post, :one_through_one, :author)
|
239
256
|
# or
|
240
|
-
Post.must_have_association(:one_through_one, :author)
|
257
|
+
_(Post).must_have_association(:one_through_one, :author)
|
241
258
|
end
|
242
259
|
|
243
260
|
# definition of args
|
@@ -253,234 +270,302 @@ assert_association(
|
|
253
270
|
<br>
|
254
271
|
<br>
|
255
272
|
|
256
|
-
|
273
|
+
---
|
257
274
|
|
258
275
|
<br>
|
259
276
|
|
260
|
-
## Validations
|
261
|
-
|
262
|
-
If you are using the recommended `:validation_class_methods` plugin in your app, the following instance validation methods are supported:
|
263
|
-
|
264
|
-
* `assert_validates_presence()`
|
265
|
-
|
266
|
-
* `assert_validates_exact_length()`
|
267
|
-
|
268
|
-
* `assert_validates_length_range()`
|
269
|
-
|
270
|
-
* `assert_validates_max_length()`
|
271
|
-
|
272
|
-
* `assert_validates_min_length()`
|
273
|
-
|
274
|
-
* `assert_validates_format()`
|
275
|
-
|
276
|
-
* `assert_validates_inclusion()`
|
277
|
-
|
278
|
-
* `assert_validates_integer()`
|
277
|
+
## Model Validations
|
279
278
|
|
280
|
-
|
279
|
+
If you are using the recommended `:validation_class_methods` plugin in your app, the following
|
280
|
+
instance validation methods are supported:
|
281
281
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
282
|
+
- `#assert_validates_presence()`
|
283
|
+
- `#assert_validates_exact_length()`
|
284
|
+
- `#assert_validates_length_range()`
|
285
|
+
- `#assert_validates_max_length()`
|
286
|
+
- `#assert_validates_min_length()`
|
287
|
+
- `#assert_validates_format()`
|
288
|
+
- `#assert_validates_inclusion()`
|
289
|
+
- `#assert_validates_integer()`
|
290
|
+
- `#assert_validates_numericality()`
|
291
|
+
- `#assert_validates_uniqueness()`
|
292
|
+
- `#assert_validates_acceptance()`
|
293
|
+
- `#assert_validates_confirmation()`
|
287
294
|
|
288
295
|
With all valid options checked
|
289
296
|
|
297
|
+
<br>
|
298
|
+
|
290
299
|
---
|
291
300
|
|
292
|
-
|
293
|
-
|
301
|
+
### `#assert_validates_presence(:model, :attribute, :opts, :msg)`
|
302
|
+
|
303
|
+
alias: `#assert_validates_presence_of(:attribute, :opts, :msg)`
|
294
304
|
|
295
305
|
Test for validating presence of a model attribute
|
296
306
|
|
297
307
|
```ruby
|
298
|
-
|
299
|
-
|
308
|
+
let(:m) { Post.first }
|
309
|
+
|
310
|
+
it { assert_validates_presence(m, :title) }
|
311
|
+
# or
|
312
|
+
it { _(m).must_validate_presence_of(:title, { message: '...' }) }
|
300
313
|
```
|
314
|
+
|
301
315
|
<br>
|
302
316
|
|
317
|
+
---
|
318
|
+
|
319
|
+
### `#assert_validates_length(:model, :attribute, :opts, :msg)`
|
303
320
|
|
304
|
-
|
305
|
-
alias `:assert_validates_length_of`
|
321
|
+
alias `#assert_validates_length_of`
|
306
322
|
|
307
323
|
Test for validating the length of a model's attribute.
|
308
324
|
|
309
325
|
Available options:
|
310
326
|
|
311
|
-
|
327
|
+
- :message - The message to use (no default, overrides :nil_message, :too_long,
|
328
|
+
:too_short, and :wrong_length options if present)
|
312
329
|
|
313
|
-
|
330
|
+
- :nil_message - The message to use use if :maximum option is used and the
|
331
|
+
value is nil (default: 'is not present')
|
314
332
|
|
315
|
-
|
333
|
+
- :too_long - The message to use use if it the value is too long
|
334
|
+
(default: 'is too long')
|
316
335
|
|
317
|
-
|
336
|
+
- :too_short - The message to use use if it the value is too short
|
337
|
+
(default: 'is too short')
|
318
338
|
|
319
|
-
|
339
|
+
- :wrong_length - The message to use use if it the value is not valid
|
340
|
+
(default: 'is the wrong length')
|
320
341
|
|
321
342
|
Size related options:
|
322
343
|
|
323
|
-
|
344
|
+
- :is - The exact size required for the value to be valid (no default)
|
324
345
|
|
325
|
-
|
346
|
+
- :minimum - The minimum size allowed for the value (no default)
|
326
347
|
|
327
|
-
|
348
|
+
- :maximum - The maximum size allowed for the value (no default)
|
328
349
|
|
329
|
-
|
350
|
+
- :within - The array/range that must include the size of the value for it to
|
351
|
+
be valid (no default)
|
330
352
|
|
331
353
|
```ruby
|
332
|
-
|
333
|
-
|
354
|
+
let(:m) { Post.first }
|
355
|
+
|
356
|
+
it { assert_validates_length(m, :title, { maximum: 12 }) }
|
357
|
+
# or
|
358
|
+
it { _(m).must_validate_length_of(:title, { within: 4..12 }) }
|
334
359
|
```
|
360
|
+
|
335
361
|
<br>
|
336
362
|
|
363
|
+
---
|
364
|
+
|
365
|
+
### `#assert_validates_exact_length(:model, :attribute, :exact_length, :opts, :msg)`
|
337
366
|
|
338
|
-
|
339
|
-
alias: `:assert_validates_exact_length_of`
|
367
|
+
alias: `#assert_validates_exact_length_of`
|
340
368
|
|
341
369
|
Test for validating the exact length of a model's attribute.
|
342
370
|
|
343
371
|
```ruby
|
344
|
-
|
345
|
-
|
372
|
+
let(:m) { Post.first }
|
373
|
+
|
374
|
+
it { assert_validates_exact_length(m, :title, 12, { message: '...' }) }
|
375
|
+
# or
|
376
|
+
it { _(m).must_validate_exact_length_of(:title, 12, { message: '...' }) }
|
346
377
|
```
|
378
|
+
|
347
379
|
<br>
|
348
380
|
|
381
|
+
---
|
382
|
+
|
383
|
+
### `#assert_validates_length_range(:model, :attribute, :range, :opts, :msg)`
|
349
384
|
|
350
|
-
|
351
|
-
alias: `:assert_validates_length_range_of`
|
385
|
+
alias: `#assert_validates_length_range_of`
|
352
386
|
|
353
387
|
Test for validating the exact length of a model's attribute.
|
354
388
|
|
355
389
|
```ruby
|
356
|
-
|
357
|
-
|
390
|
+
let(:m) { Post.first }
|
391
|
+
|
392
|
+
it { assert_validates_length_range(m, :title, 4..12, { message: '...' }) }
|
393
|
+
# or
|
394
|
+
it { _(m).must_validate_length_range_of(:title, 4..12, { message: '...' }) }
|
358
395
|
```
|
359
396
|
|
360
397
|
<br>
|
361
398
|
|
399
|
+
---
|
400
|
+
|
401
|
+
### `#assert_validates_max_length(:model, :attribute, :max_length, :opts, :msg)`
|
362
402
|
|
363
|
-
|
364
|
-
alias: `:assert_validates_max_length_of`
|
403
|
+
alias: `#assert_validates_max_length_of`
|
365
404
|
|
366
405
|
Test for validating the maximum length of a model's attribute.
|
367
406
|
|
368
407
|
```ruby
|
369
|
-
|
370
|
-
|
408
|
+
let(:m) { Post.first }
|
409
|
+
|
410
|
+
it { assert_validates_max_length(m, :title, 12, { message: '...' }) }
|
411
|
+
# or
|
412
|
+
it { _(m).must_validate_max_length_of(:title, 12, { message: '...' }) }
|
371
413
|
```
|
372
414
|
|
373
415
|
<br>
|
374
416
|
|
417
|
+
---
|
375
418
|
|
376
|
-
|
377
|
-
|
419
|
+
### `#assert_validates_min_length(:model, :attribute, :min_length, :opts, :msg)`
|
420
|
+
|
421
|
+
alias: `#assert_validates_min_length_of`
|
378
422
|
|
379
423
|
Test for validating the minimum length of a model's attribute.
|
380
424
|
|
381
425
|
```ruby
|
382
|
-
|
383
|
-
|
426
|
+
let(:m) { Post.first }
|
427
|
+
|
428
|
+
it { assert_validates_min_length(m, :title, 12, { message: '...' }) }
|
429
|
+
# or
|
430
|
+
it { _(m).must_validate_min_length_of(:title, 12, { message: '...' }) }
|
384
431
|
```
|
385
432
|
|
386
433
|
<br>
|
387
434
|
|
435
|
+
---
|
436
|
+
|
437
|
+
### `#assert_validates_format(:model, :attribute, :opts, :msg)`
|
388
438
|
|
389
|
-
|
390
|
-
alias: `:assert_validates_format_of`
|
439
|
+
alias: `#assert_validates_format_of`
|
391
440
|
|
392
441
|
Test for validating the format of a model's attribute with a regexp.
|
393
442
|
|
394
443
|
```ruby
|
395
|
-
|
396
|
-
|
444
|
+
let(:m) { Post.first }
|
445
|
+
|
446
|
+
it { assert_validates_format(m, :title, { with: /[a-z+]/ }) }
|
447
|
+
# or
|
448
|
+
it { _(m).must_validate_format_of(:title, { with: /[a-z]+/ }) }
|
397
449
|
```
|
398
450
|
|
399
451
|
<br>
|
400
452
|
|
453
|
+
---
|
454
|
+
|
455
|
+
### `#assert_validates_inclusion(:model, :attribute, :opts, :msg)`
|
401
456
|
|
402
|
-
|
403
|
-
alias: `:assert_validates_inclusion_of`
|
457
|
+
alias: `#assert_validates_inclusion_of`
|
404
458
|
|
405
|
-
Test for validating that a model's attribute is within a specified range or
|
459
|
+
Test for validating that a model's attribute is within a specified range or
|
460
|
+
set of values.
|
406
461
|
|
407
462
|
```ruby
|
408
|
-
|
409
|
-
|
463
|
+
let(:m) { Post.first }
|
464
|
+
|
465
|
+
it { assert_validates_inclusion(m, :status, { in: [:a, :b, :c] }) }
|
466
|
+
# or
|
467
|
+
it { _(m).must_validate_inclusion_of(:status, { in: [:a, :b, :c] }) }
|
410
468
|
```
|
411
469
|
|
412
470
|
<br>
|
413
471
|
|
472
|
+
---
|
473
|
+
|
474
|
+
### `#assert_validates_integer(:model, :attribute, :opts, :msg)`
|
414
475
|
|
415
|
-
#### `assert_validates_integer(obj, attribute, opts = {}, msg = nil)`
|
416
476
|
alias: none
|
417
477
|
|
418
478
|
Test for validating that a a model's attribute is an integer.
|
419
479
|
|
420
480
|
```ruby
|
421
|
-
|
422
|
-
|
481
|
+
let(:m) { Post.first }
|
482
|
+
|
483
|
+
it { assert_validates_integer(m, :author_id, { message: '...' }) }
|
484
|
+
# or
|
485
|
+
it { _(m).must_validate_integer_of(:author_id, { message: '...' }) }
|
423
486
|
```
|
424
487
|
|
425
488
|
<br>
|
426
489
|
|
490
|
+
---
|
427
491
|
|
428
|
-
|
429
|
-
|
492
|
+
### `#assert_validates_numericality(:model, :attribute, :opts, :msg)`
|
493
|
+
|
494
|
+
alias: `#assert_validates_numericality_of`
|
430
495
|
|
431
496
|
Test for validating that a model's attribute is numeric (number).
|
432
497
|
|
433
498
|
```ruby
|
434
|
-
|
435
|
-
|
499
|
+
let(:m) { Post.first }
|
500
|
+
|
501
|
+
it { assert_validates_numericality(m, :author_id, { message: '...' }) }
|
502
|
+
# or
|
503
|
+
it { _(m).must_validate_numericality_of(:author_id, { message: '...' }) }
|
436
504
|
```
|
437
505
|
|
438
506
|
<br>
|
439
507
|
|
508
|
+
---
|
509
|
+
|
510
|
+
### `#assert_validates_uniqueness(:model, :attribute, :opts, :msg)`
|
440
511
|
|
441
|
-
|
442
|
-
alias: `:assert_validates_uniqueness_of`
|
512
|
+
alias: `#assert_validates_uniqueness_of`
|
443
513
|
|
444
514
|
Test for validating that a model's attribute is unique.
|
445
515
|
|
446
516
|
```ruby
|
447
|
-
|
448
|
-
|
517
|
+
let(:m) { Post.first }
|
518
|
+
|
519
|
+
it { assert_validates_uniqueness(m, :urlslug, { message: '...' }) }
|
520
|
+
# or
|
521
|
+
it { _(m).must_validate_uniqueness_of(:urlslug, { message: '...' }) }
|
449
522
|
```
|
450
523
|
|
451
524
|
<br>
|
452
525
|
|
526
|
+
---
|
527
|
+
|
528
|
+
### `#assert_validates_acceptance(:model, :attribute, :opts, :msg)`
|
453
529
|
|
454
|
-
|
455
|
-
alias: `assert_validates_acceptance_of`
|
530
|
+
alias: `#assert_validates_acceptance_of`
|
456
531
|
|
457
532
|
Test for validating the acceptance of a model's attribute.
|
458
533
|
|
459
534
|
```ruby
|
460
|
-
|
461
|
-
|
535
|
+
let(:m) { Order.new }
|
536
|
+
|
537
|
+
it { assert_validates_acceptance(m, :toc, { message: '...' }) }
|
538
|
+
# or
|
539
|
+
it { _(m).must_validate_acceptance_of(:toc, { message: '...' }) }
|
462
540
|
```
|
463
541
|
|
464
542
|
<br>
|
465
543
|
|
544
|
+
---
|
545
|
+
|
546
|
+
### `#assert_validates_confirmation(:model, :attribute, :opts, :msg)`
|
466
547
|
|
467
|
-
|
468
|
-
alias: `:assert_validates_confirmation_of`
|
548
|
+
alias: `#assert_validates_confirmation_of`
|
469
549
|
|
470
550
|
Test for validating the confirmation of a model's attribute.
|
471
551
|
|
472
552
|
```ruby
|
473
|
-
|
474
|
-
|
553
|
+
let(:m) { User.new }
|
554
|
+
|
555
|
+
it { assert_validates_confirmation(m, :password, { message: '...' }) }
|
556
|
+
# or
|
557
|
+
it { _(m).must_validate_confirmation_of(:password, { message: '...' }) }
|
475
558
|
```
|
476
559
|
|
477
560
|
<br>
|
478
561
|
|
562
|
+
---
|
479
563
|
|
480
564
|
Each validation assertion have a responding negative test, ie: `refute_validate_presence()`
|
481
565
|
|
566
|
+
<br>
|
482
567
|
|
483
|
-
### Usage
|
568
|
+
### Usage Example
|
484
569
|
|
485
570
|
A model defined with validations like this:
|
486
571
|
|
@@ -505,17 +590,20 @@ let(:m) { Post.first }
|
|
505
590
|
|
506
591
|
it "should validate presence of :title column" do
|
507
592
|
assert_validates_presence(m, :title)
|
593
|
+
# or
|
594
|
+
_(m).must_validate_presence_of(:title)
|
508
595
|
end
|
509
596
|
|
510
597
|
it "should validate format of :title column with regexp" do
|
511
598
|
assert_validates_format(m, :title, /\w+/)
|
599
|
+
# or
|
600
|
+
_(m).must_validate_format_of(:title, /\w+/)
|
512
601
|
end
|
513
602
|
```
|
514
603
|
|
515
|
-
<br>
|
516
604
|
<br>
|
517
605
|
|
518
|
-
|
606
|
+
---
|
519
607
|
|
520
608
|
<br>
|
521
609
|
|
@@ -523,10 +611,13 @@ end
|
|
523
611
|
|
524
612
|
This gem also contains a collection of "helpers" that aid working with Sequel models:
|
525
613
|
|
614
|
+
### `#assert_timestamped_model(:model, :opts, :msg)`
|
526
615
|
|
527
|
-
|
616
|
+
Quickly test if a model class is timestamped with `.plugin(:timestamps)` with
|
617
|
+
[Sequel-Timestamps](http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/Timestamps.html)
|
528
618
|
|
529
|
-
|
619
|
+
> [!NOTE]
|
620
|
+
> The test examples below uses the [minitest-assert_errors](https://github.com/kematzy/minitest-assert_errors) package.
|
530
621
|
|
531
622
|
|
532
623
|
```ruby
|
@@ -534,123 +625,157 @@ Quickly test if a model class is timestamped with .plugin(:timestamps) with [Seq
|
|
534
625
|
class Comment < Sequel::Model
|
535
626
|
plugin(:timestamps)
|
536
627
|
end
|
537
|
-
|
628
|
+
|
629
|
+
assert_no_error { assert_timestamped_model(Comment) }
|
538
630
|
|
539
631
|
# on a non-timestamped model
|
540
632
|
class Post < Sequel::Model; end
|
541
|
-
proc { assert_timestamped_model(Post) }.must_have_error(/Not a \.plugin\(:timestamps\) model, available plugins are/)
|
542
|
-
```
|
543
633
|
|
544
|
-
|
634
|
+
msg = /Not a \.plugin\(:timestamps\) model, available plugins are/
|
545
635
|
|
546
|
-
|
636
|
+
assert_error_raised(msg) { assert_timestamped_model(Post) }
|
637
|
+
```
|
638
|
+
|
639
|
+
> [!TIP]
|
640
|
+
> You can also pass attributes to the created model in the tests via the `opts` hash like this:
|
547
641
|
|
548
642
|
```ruby
|
549
|
-
|
643
|
+
assert_no_error do
|
644
|
+
assert_timestamped_model(Comment, {body: "I think...", email: "e@email.com"})
|
645
|
+
end
|
550
646
|
```
|
551
|
-
|
552
|
-
Timestamps can be declared globally for all models via `Sequel::Model.plugin(:timestamps)` before the models are migrated.
|
553
647
|
|
648
|
+
Timestamps can be declared globally for all models via `Sequel::Model.plugin(:timestamps)` before
|
649
|
+
the models are migrated.
|
650
|
+
|
651
|
+
<br>
|
652
|
+
|
653
|
+
---
|
554
654
|
|
555
|
-
|
655
|
+
### `#assert_timestamped_model_instance(:model, :opts, :msg)`
|
556
656
|
|
557
|
-
Test if a model instance is timestamped with the .plugin(:timestamps) via
|
657
|
+
Test if a model instance is timestamped with the .plugin(:timestamps) via
|
658
|
+
[Sequel-Timestamps](http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/Timestamps.html)
|
558
659
|
|
559
660
|
```ruby
|
560
661
|
let(:m) { Post.create(title: "Dummy") }
|
561
|
-
proc { assert_timestamped_model_instance(m) }.wont_have_error
|
562
|
-
```
|
563
662
|
|
663
|
+
assert_no_error { assert_timestamped_model_instance(m) }
|
664
|
+
```
|
564
665
|
|
565
666
|
You can also test if an updated record is correctly timestamped
|
566
667
|
|
567
668
|
```ruby
|
568
669
|
m.title = "Updated"
|
569
670
|
m.save
|
570
|
-
|
671
|
+
|
672
|
+
assert_no_error do
|
673
|
+
assert_timestamped_model_instance(m, updated_record: true)
|
674
|
+
end
|
571
675
|
```
|
572
676
|
|
573
677
|
Or alternatively test if an updated record is wrongly timestamped
|
574
678
|
|
575
679
|
```ruby
|
576
680
|
let(:m) { Post.create(title: "Dummy", updated_at: Time.now) }
|
577
|
-
proc { assert_timestamped_model_instance(m, updated_record: false) }.must_have_error(/expected #.updated_at to be NIL on new record/)
|
578
|
-
```
|
579
681
|
|
682
|
+
msg = /expected #.updated_at to be NIL on new record/
|
683
|
+
|
684
|
+
assert_error_raised(msg) do
|
685
|
+
assert_timestamped_model_instance(m, updated_record: false)
|
686
|
+
end
|
687
|
+
```
|
580
688
|
|
581
689
|
<br>
|
582
690
|
|
583
|
-
|
691
|
+
---
|
692
|
+
|
693
|
+
### `#assert_paranoid_model(:model, :opts, :msg)`
|
584
694
|
|
585
|
-
Test if a model class is paranoid with .plugin(:paranoid) via
|
695
|
+
Test if a model class is paranoid with .plugin(:paranoid) via
|
696
|
+
[Sequel-Paranoid](https://github.com/sdepold/sequel-paranoid)
|
586
697
|
|
587
698
|
```ruby
|
588
699
|
# Declared locally in the Model
|
589
700
|
class Comment < Sequel::Model
|
590
701
|
plugin(:paranoid)
|
591
702
|
end
|
592
|
-
|
703
|
+
|
704
|
+
assert_no_error { assert_paranoid_model(Comment) }
|
593
705
|
|
594
706
|
# on a non-paranoid model
|
595
707
|
class Post < Sequel::Model; end
|
596
|
-
proc { assert_paranoid_model(Post) }.must_have_error(/Not a plugin\(:paranoid\) model, available plugins are/)
|
597
|
-
```
|
598
708
|
|
599
|
-
|
709
|
+
msg = /Not a plugin\(:paranoid\) model, available plugins are/
|
710
|
+
|
711
|
+
assert_error_raised(msg) { assert_paranoid_model(Post) }
|
712
|
+
```
|
600
713
|
|
601
|
-
|
714
|
+
> [!TIP]
|
715
|
+
> You can also pass attributes to the created model in the tests via the `opts` hash like this:
|
602
716
|
|
603
717
|
```ruby
|
604
|
-
|
718
|
+
assert_no_error do
|
719
|
+
assert_timestamped_model(Comment, { body: "I think...", email: "e@email.com" })
|
720
|
+
end
|
605
721
|
```
|
606
722
|
|
607
|
-
|
608
723
|
<br>
|
609
724
|
|
610
|
-
|
725
|
+
---
|
611
726
|
|
612
|
-
|
727
|
+
### `#refute_timestamped_model(:model, :msg)`
|
613
728
|
|
729
|
+
Test to ensure a model is NOT declared with .plugin(:timestamps) using
|
730
|
+
[Sequel-Timestamps](http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/Timestamps.html)
|
614
731
|
|
615
|
-
Test if a model class is paranoid with .plugin(:paranoid) via
|
732
|
+
Test if a model class is paranoid with .plugin(:paranoid) via
|
733
|
+
[Sequel-Paranoid](https://github.com/sdepold/sequel-paranoid)
|
616
734
|
|
617
735
|
```ruby
|
618
736
|
class Comment < Sequel::Model
|
619
737
|
plugin(:timestamps)
|
620
738
|
end
|
621
|
-
|
739
|
+
|
740
|
+
msg = /expected Comment to NOT be a :timestamped model, but it was/
|
741
|
+
|
742
|
+
assert_error_raised(msg) do
|
743
|
+
refute_timestamped_model(Comment)
|
744
|
+
end
|
622
745
|
|
623
746
|
# on a non-timestamped model
|
624
747
|
class Post < Sequel::Model; end
|
748
|
+
|
625
749
|
it { refute_timestamped_model(Post) }
|
626
750
|
```
|
627
751
|
|
628
752
|
<br>
|
629
753
|
|
630
|
-
|
754
|
+
---
|
755
|
+
|
756
|
+
### `#refute_paranoid_model(:model, :msg)`
|
631
757
|
|
632
|
-
Test to ensure a model is NOT declared with .plugin(:paranoid) using
|
758
|
+
Test to ensure a model is NOT declared with .plugin(:paranoid) using
|
759
|
+
[Sequel-Paranoid](https://github.com/sdepold/sequel-paranoid)
|
633
760
|
|
634
761
|
```ruby
|
635
762
|
class Comment < Sequel::Model
|
636
763
|
plugin(:paranoid)
|
637
764
|
end
|
638
|
-
|
765
|
+
|
766
|
+
msg = /expected Comment to NOT be a :paranoid model, but it was/
|
767
|
+
|
768
|
+
assert_error_raised(msg) { refute_paranoid_model(Comment) }
|
639
769
|
|
640
770
|
# on a non-paranoid model
|
641
771
|
class Post < Sequel::Model; end
|
772
|
+
|
642
773
|
it { refute_paranoid_model(Post) }
|
643
774
|
```
|
644
775
|
|
645
|
-
|
646
776
|
<br>
|
647
777
|
|
648
|
-
|
649
|
-
<br>
|
650
|
-
|
651
|
-
----
|
652
|
-
|
653
|
-
<br>
|
778
|
+
---
|
654
779
|
|
655
780
|
## Miscellaneous Helpers
|
656
781
|
|
@@ -658,7 +783,7 @@ This gem also contains a collection of "helpers" that aid working with Sequel mo
|
|
658
783
|
|
659
784
|
<br>
|
660
785
|
|
661
|
-
|
786
|
+
### `#ensure_working_CRUD(:model, :attribute)`
|
662
787
|
|
663
788
|
Enables quick tests to ensure that the basic CRUD functionality is working correctly for a Model
|
664
789
|
|
@@ -666,20 +791,21 @@ Enables quick tests to ensure that the basic CRUD functionality is working corre
|
|
666
791
|
ensure_working_CRUD(User, :name)
|
667
792
|
```
|
668
793
|
|
669
|
-
|
670
|
-
|
671
|
-
|
794
|
+
> [!NOTE]
|
795
|
+
> - the passed `:model` argument must be the actual Model class and NOT a string or symbol
|
796
|
+
> - the passed attribute `:attribute` must be a String attribute or the tests will fail
|
672
797
|
|
673
|
-
|
798
|
+
<br>
|
799
|
+
|
800
|
+
## Dependencies
|
674
801
|
|
675
802
|
This test depends upon being able to create a new model instance for each test via using
|
676
803
|
[Sequel Factory's](https://github.com/mjackson/sequel-factory) `#make()` method
|
677
804
|
|
678
|
-
|
679
805
|
<br>
|
680
806
|
<br>
|
681
807
|
|
682
|
-
|
808
|
+
---
|
683
809
|
|
684
810
|
<br>
|
685
811
|
|
@@ -694,67 +820,66 @@ gem 'minitest-sequel'
|
|
694
820
|
And then execute:
|
695
821
|
|
696
822
|
```bash
|
697
|
-
|
823
|
+
bundle
|
698
824
|
```
|
699
825
|
|
700
826
|
Or install it yourself as:
|
701
827
|
|
702
828
|
```bash
|
703
|
-
|
829
|
+
gem install minitest-sequel
|
704
830
|
```
|
705
831
|
|
706
|
-
##
|
707
|
-
|
708
|
-
In your project's `spec/spec_helper.rb` or `test/test_helper.rb` file ensure the following code is present:
|
832
|
+
## Within Your Project
|
709
833
|
|
834
|
+
In your project's `spec/spec_helper.rb` or `test/test_helper.rb` file ensure
|
835
|
+
the following code is present:
|
710
836
|
|
711
|
-
```ruby
|
837
|
+
```ruby
|
712
838
|
gem 'minitest'
|
713
839
|
|
714
840
|
require 'minitest/autorun'
|
715
|
-
require 'minitest/sequel' # NB!!
|
841
|
+
require 'minitest/sequel' # NB!! must be loaded after minitest/autorun
|
716
842
|
|
717
843
|
require 'sqlite3' # using sqlite for tests
|
718
844
|
|
719
|
-
|
845
|
+
# The preferred default validations plugin, which uses class-level methods.
|
720
846
|
Sequel::Model.plugin(:validation_class_methods)
|
721
847
|
|
722
|
-
|
848
|
+
# connect to database
|
723
849
|
DB = Sequel.sqlite # :memory
|
724
850
|
|
725
|
-
|
851
|
+
## add migrations and seeds below
|
726
852
|
|
727
853
|
DB.create_table(:posts) do
|
728
854
|
primary_key :id
|
729
855
|
# <snip...>
|
730
856
|
end
|
731
857
|
|
732
|
-
|
858
|
+
# <snip...>
|
733
859
|
```
|
734
860
|
|
735
861
|
Then in your tests you should be good to go when using the sequel assertions.
|
736
862
|
|
737
|
-
|
738
|
-
|
739
863
|
## Development
|
740
864
|
|
741
|
-
After checking out the repo, run `bundle install` to install all dependencies.
|
865
|
+
After checking out the repo, run `bundle install` to install all dependencies.
|
866
|
+
Then, run `rake spec` to run the tests.
|
742
867
|
|
743
868
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
744
869
|
|
745
|
-
To release a new version, update the version number in `version.rb`, and then run
|
746
|
-
which will create a git tag for the version, push git commits and
|
747
|
-
[rubygems.org](https://rubygems.org).
|
748
|
-
|
870
|
+
To release a new version, update the version number in `version.rb`, and then run
|
871
|
+
`bundle exec rake release`, which will create a git tag for the version, push git commits and
|
872
|
+
tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
749
873
|
|
750
874
|
## Contributing
|
751
875
|
|
752
|
-
Bug reports and pull requests are welcome on GitHub at
|
753
|
-
|
754
|
-
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere
|
755
|
-
to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
876
|
+
Bug reports and pull requests are welcome on GitHub at
|
877
|
+
[Issues](https://github.com/kematzy/minitest-sequel/issues).
|
756
878
|
|
879
|
+
This project is intended to be a safe, welcoming space for collaboration, and contributors are
|
880
|
+
expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
757
881
|
|
758
882
|
## License
|
759
883
|
|
760
|
-
The gem is available as open source under the terms of the
|
884
|
+
The gem is available as open source under the terms of the
|
885
|
+
[MIT License](http://opensource.org/licenses/MIT).
|