rspec-activerecord-expectations 2.1.1 → 2.2.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +54 -5
- data/lib/rspec/activerecord/expectations/matchers/transaction_matcher.rb +70 -0
- data/lib/rspec/activerecord/expectations/query_inspector.rb +8 -3
- data/lib/rspec/activerecord/expectations.rb +17 -0
- data/rspec-activerecord-expectations.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3205b050d5f2164b5bc72de9fe29a0f6d988cd869ecd6703a09b83b2550bb02e
|
4
|
+
data.tar.gz: d43d363888f5c8f85dc551fae7d1381a945ac304c597192544ffd1506d1f7495
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a98cfac5ba127c3e5f7bd2b42ef48fa56e6750e75d0ab841988b076a2a39c0ca13e5d67e534020fd81af3b7885cba3d192c23a2fbb0b4ccd0d8e725e3cafb147
|
7
|
+
data.tar.gz: 65347df27d406531b1ea594bfe9a3d9b6405c75ad5f8be5c3f52f668e3d976e0e73c5e1560caeb308cb203b73547ab18c0ffd758aff0e913a9f010665a0a6595
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [2.2.0] - 2022-01-14
|
4
|
+
- Adds transaction matcher to verify that code was executed within a
|
5
|
+
transaction at minimum
|
6
|
+
- Transaction matcher also allows for commits and rollbacks
|
7
|
+
- Update README for accompanying functionality
|
8
|
+
|
3
9
|
## [2.1.1] - 2022-01-12
|
4
10
|
- Gemspec is really generated using the version of ruby that's locally in use.
|
5
11
|
Update that build artifact to use non-java dependencies.
|
data/README.md
CHANGED
@@ -181,7 +181,57 @@ expect {}.to execute.exactly(20).transaction_queries
|
|
181
181
|
categories, nor are queries that load the DB schema.
|
182
182
|
|
183
183
|
**Note:** Destroy and delete queries are both condensed into the matcher for
|
184
|
-
`destroy_queries`.
|
184
|
+
the errorthe error `destroy_queries`.
|
185
|
+
|
186
|
+
## Transaction Management
|
187
|
+
|
188
|
+
Sometimes, it makes sense to monitor whether database transactions were
|
189
|
+
successful or not. This is very similar to using `expect{}.to change(SomeModel,
|
190
|
+
:count)` in a spec, but nonetheless it can be useful to assert transactions
|
191
|
+
themselves. Some assertions are available for this purpose.
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
expect {}.to execute_a_transaction
|
195
|
+
expect {}.to rollback_a_transaction
|
196
|
+
expect {}.to roll_back_a_transaction
|
197
|
+
expect {}.to commit_a_transaction
|
198
|
+
```
|
199
|
+
|
200
|
+
A complication to this scheme is that Rails tries not to make unnecessary database
|
201
|
+
calls, which means that attempting to save a model that has failing validations
|
202
|
+
won't actually attempt to save to the database.
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
expect {
|
206
|
+
MyClass.create!(required_field: nil)
|
207
|
+
}.to rollback_a_transaction
|
208
|
+
```
|
209
|
+
|
210
|
+
This assertion will fail, as `create!` will never make it as far as the
|
211
|
+
database. That said, if you manually create a transaction, _and you select
|
212
|
+
data within that transaction_, you may assert a rollback.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
expect {
|
216
|
+
MyClass.first # triggers the transaction
|
217
|
+
MyClass.create!(required_field: nil)
|
218
|
+
}.to rollback_a_transaction
|
219
|
+
```
|
220
|
+
|
221
|
+
It you need to make transaction-related assertions of this sort, your best bet
|
222
|
+
may be to assert that a commit statement was _not_ issued.
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
expect do
|
226
|
+
MyClass.create!(required_field: nil)
|
227
|
+
rescue
|
228
|
+
# NOOP
|
229
|
+
end.not_to rollback_a_transaction
|
230
|
+
```
|
231
|
+
|
232
|
+
Note that ActiveRecord will not only roll back the transaction, but also
|
233
|
+
re-raise errors. As such, it's necessary in this example to rescue that
|
234
|
+
error in order for the test to fail.
|
185
235
|
|
186
236
|
## Future Planned Functionality
|
187
237
|
|
@@ -194,14 +244,13 @@ expect {}.to execute.at_least(2).load_queries("Audited::Audit")
|
|
194
244
|
expect {}.to execute.at_least(2).activerecord_queries
|
195
245
|
expect {}.to execute.at_least(2).hand_rolled_queries
|
196
246
|
|
197
|
-
expect {}.not_to rollback_transaction.exactly(5).times
|
198
|
-
expect {}.not_to commit_transaction.once
|
199
|
-
expect {}.to run_a_transaction
|
200
|
-
|
201
247
|
expect {}.to create.exactly(5).of_type(User)
|
202
248
|
expect {}.to insert.exactly(5).subscription_changes
|
203
249
|
expect {}.to update.exactly(2).of_any_type
|
204
250
|
expect {}.to delete.exactly(2).of_any_type
|
251
|
+
|
252
|
+
expect {}.to commit_a_transaction.once
|
253
|
+
expect {}.to rollback_a_transaction.exactly(5).times
|
205
254
|
```
|
206
255
|
|
207
256
|
- warn if we smite any built in methods (or methods from other libs)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module RSpec::ActiveRecord::Expectations
|
2
|
+
module Matchers
|
3
|
+
class TransactionMatcher
|
4
|
+
def initialize(transaction_type)
|
5
|
+
@collector = Collector.new
|
6
|
+
@transaction = transaction_type
|
7
|
+
end
|
8
|
+
|
9
|
+
def supports_block_expectations?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(block)
|
14
|
+
block.call
|
15
|
+
|
16
|
+
@count = @collector.queries_of_type(@transaction)
|
17
|
+
@count > 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure_message
|
21
|
+
type_msg = case @transaction
|
22
|
+
when :transaction_queries
|
23
|
+
"execute a transaction"
|
24
|
+
when :rollback_queries
|
25
|
+
"roll back a transaction"
|
26
|
+
when :commit_queries
|
27
|
+
"commit a transaction"
|
28
|
+
end
|
29
|
+
|
30
|
+
"expected block to #{type_msg}, but it didn't do so"
|
31
|
+
end
|
32
|
+
|
33
|
+
def failure_message_when_negated
|
34
|
+
if @count == 1
|
35
|
+
negated_message_singular
|
36
|
+
else
|
37
|
+
negated_message_plural
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def negated_message_singular
|
44
|
+
pre_msg, post_msg = case @transaction
|
45
|
+
when :transaction_queries
|
46
|
+
["execute a transaction", "executed one"]
|
47
|
+
when :rollback_queries
|
48
|
+
["roll back a transaction", "rolled one back"]
|
49
|
+
when :commit_queries
|
50
|
+
["commit a transaction", "committed one"]
|
51
|
+
end
|
52
|
+
|
53
|
+
"expected block not to #{pre_msg}, but it #{post_msg}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def negated_message_plural
|
57
|
+
pre_msg, post_msg = case @transaction
|
58
|
+
when :transaction_queries
|
59
|
+
["execute a transaction", "executed #{@count} transactions"]
|
60
|
+
when :rollback_queries
|
61
|
+
["roll back a transaction", "rolled back #{@count} transactions"]
|
62
|
+
when :commit_queries
|
63
|
+
["commit a transaction", "committed #{@count} transactions"]
|
64
|
+
end
|
65
|
+
|
66
|
+
"expected block not to #{pre_msg}, but it #{post_msg}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,14 +1,19 @@
|
|
1
1
|
module RSpec::ActiveRecord::Expectations
|
2
2
|
class QueryInspector
|
3
3
|
def self.valid_query_types
|
4
|
-
[:queries, :schema_queries, :
|
5
|
-
:
|
4
|
+
[:queries, :schema_queries, :insert_queries, :load_queries,
|
5
|
+
:destroy_queries, :exists_queries,
|
6
|
+
:transaction_queries, :commit_queries, :rollback_queries]
|
6
7
|
end
|
7
8
|
|
8
9
|
def categorize(query)
|
9
10
|
if query[:name] == "SCHEMA"
|
10
11
|
[:schema_queries]
|
11
|
-
elsif query[:
|
12
|
+
elsif query[:sql] =~ /^commit/i
|
13
|
+
[:commit_queries]
|
14
|
+
elsif query[:sql] =~ /^rollback/i
|
15
|
+
[:rollback_queries]
|
16
|
+
elsif query[:name] == "TRANSACTION"
|
12
17
|
[:transaction_queries]
|
13
18
|
elsif query[:name] =~ /Create$/
|
14
19
|
[:queries, :insert_queries]
|
@@ -8,6 +8,22 @@ module RSpec
|
|
8
8
|
def repeatedly_load(klass)
|
9
9
|
Matchers::LoadMatcher.new(klass)
|
10
10
|
end
|
11
|
+
|
12
|
+
def execute_a_transaction
|
13
|
+
Matchers::TransactionMatcher.new(:transaction_queries)
|
14
|
+
end
|
15
|
+
|
16
|
+
def rollback_a_transaction
|
17
|
+
Matchers::TransactionMatcher.new(:rollback_queries)
|
18
|
+
end
|
19
|
+
|
20
|
+
def roll_back_a_transaction
|
21
|
+
Matchers::TransactionMatcher.new(:rollback_queries)
|
22
|
+
end
|
23
|
+
|
24
|
+
def commit_a_transaction
|
25
|
+
Matchers::TransactionMatcher.new(:commit_queries)
|
26
|
+
end
|
11
27
|
end
|
12
28
|
end
|
13
29
|
end
|
@@ -17,3 +33,4 @@ require_relative 'expectations/query_inspector'
|
|
17
33
|
require_relative 'expectations/collector'
|
18
34
|
require_relative 'expectations/matchers/query_count_matcher'
|
19
35
|
require_relative 'expectations/matchers/load_matcher'
|
36
|
+
require_relative 'expectations/matchers/transaction_matcher'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-activerecord-expectations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Mastey
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/rspec/activerecord/expectations/errors.rb
|
105
105
|
- lib/rspec/activerecord/expectations/matchers/load_matcher.rb
|
106
106
|
- lib/rspec/activerecord/expectations/matchers/query_count_matcher.rb
|
107
|
+
- lib/rspec/activerecord/expectations/matchers/transaction_matcher.rb
|
107
108
|
- lib/rspec/activerecord/expectations/query_inspector.rb
|
108
109
|
- rspec-activerecord-expectations.gemspec
|
109
110
|
homepage: https://github.com/jmmastey/rspec-activerecord-expectations
|