rspec-activerecord-expectations 1.0.1 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 202f92144b220ec281763d132152aa1bf3cced42d09273d3c050c8c41dab2018
4
- data.tar.gz: f4e4e5f4fce4c3db060c3ea1fcb6752d876fd8b41cc0337dc81308c6acfceb08
3
+ metadata.gz: d320c1e0f80e96c3bbb2cb07df63b941aa9bb1aa3878f9ca46e6fa1fed483569
4
+ data.tar.gz: 69487efb7a89d208d28a0d26faa3c74fc3315645803a1ec4162a6bd9f3677008
5
5
  SHA512:
6
- metadata.gz: fdbccf8e60640748b4eabc666355ac175455f0338a21a157d41eaee48f82361f45c4c921ec94ee2f3df5b9a274c72a1de868d4f7dfe5d3e2ff4480fbc08981ef
7
- data.tar.gz: d330ce04fee3e846d0591cd4f0c34599e3501715e291f7ad7956a226e7ca7d91638892a09e566f567e13daaf2287d7da95869e4c99e849043a459e7afcc599e0
6
+ metadata.gz: 7db71325cbfa0abd65c7128cceb18ba8017af399bee5cdd4502d84a988c3865605f0c5d34f858af352c1520b401651723fbf1c2335d652ec45f9ef0308a675bb
7
+ data.tar.gz: 44082fc8ad08369ea9e578f6cb3a11ec3dd7f92445b63ef4d415e10e14c79e350ded3a39828821b613513c382fd71b72db9b0669e7c14bd2e900655e03cffa5d
@@ -11,22 +11,22 @@ jobs:
11
11
  strategy:
12
12
  matrix:
13
13
  os: [ubuntu-latest, macos-latest]
14
- ruby_version: ['3.0', '2.7']
14
+ ruby-version: ['3.1', '3.0', '2.7']
15
15
  rails: ['5.0', '5.1', '5.2', '6.0', '6.1', '7.0']
16
16
 
17
17
  runs-on: ${{ matrix.os }}
18
- name: Test ruby ${{ matrix.ruby_version }} / rails ${{ matrix.rails }} / ${{ matrix.os }}
18
+ name: ruby ${{ matrix.ruby-version }}, rails ${{ matrix.rails }}, ${{ matrix.os }}
19
19
 
20
20
  steps:
21
21
  - uses: actions/checkout@v2
22
22
 
23
- - name: Set up Ruby ${{ matrix.ruby_version }}
23
+ - name: Set up Ruby ${{ matrix.ruby-version }}
24
24
  uses: ruby/setup-ruby@v1
25
25
  with:
26
- ruby_version: ${{ matrix.ruby_version }}
26
+ ruby-version: ${{ matrix.ruby-version }}
27
27
  bundler-cache: true
28
28
 
29
- - name: Install correct gems / rails version
29
+ - name: Install Gems w/ Rails ${{ matrix.rails }}
30
30
  env:
31
31
  MATRIX_RAILS_VERSION: ${{ matrix.rails }}
32
32
  run: |
@@ -40,23 +40,51 @@ jobs:
40
40
  test_legacy:
41
41
  strategy:
42
42
  matrix:
43
- os: [ubuntu-latest, macos-latest]
44
- ruby_version: ['2.6', '2.5', '2.4', '2.3']
43
+ ruby-version: ['2.6', '2.5']
45
44
  rails: ['5.0', '5.1', '5.2']
46
45
 
47
- runs-on: ${{ matrix.os }}
48
- name: Test Legacy ruby ${{ matrix.ruby }} / rails ${{ matrix.rails }} / ${{ matrix.os }}
46
+ runs-on: ubuntu-latest
47
+ name: ruby ${{ matrix.ruby-version }}, rails ${{ matrix.rails }}
48
+
49
+ steps:
50
+ - uses: actions/checkout@v2
51
+
52
+ - name: Set up Ruby ${{ matrix.ruby-version }}
53
+ uses: ruby/setup-ruby@v1
54
+ with:
55
+ ruby-version: ${{ matrix.ruby-version }}
56
+ bundler-cache: true
57
+
58
+ - name: Install Gems w/ Rails ${{ matrix.rails }}
59
+ env:
60
+ MATRIX_RAILS_VERSION: ${{ matrix.rails }}
61
+ run: |
62
+ export BUNDLE_GEMFILE="${GITHUB_WORKSPACE}/gemfiles/rails_${MATRIX_RAILS_VERSION}.gemfile"
63
+ gem install bundler
64
+ bundle install --jobs 4 --retry 3
65
+
66
+ - name: Run tests
67
+ run: bundle exec rspec
68
+
69
+ test_alt_rubies:
70
+ strategy:
71
+ matrix:
72
+ ruby-version: ['jruby', 'truffleruby']
73
+ rails: ['6.0', '6.1'] # jruby / jdbc-sqlite3 end up tightly bound to rails 6.x
74
+
75
+ runs-on: ubuntu-latest
76
+ name: ${{ matrix.ruby-version }}, rails ${{ matrix.rails }}
49
77
 
50
78
  steps:
51
79
  - uses: actions/checkout@v2
52
80
 
53
- - name: Set up Ruby ${{ matrix.ruby_version }}
81
+ - name: Set up Ruby ${{ matrix.ruby-version }}
54
82
  uses: ruby/setup-ruby@v1
55
83
  with:
56
- ruby_version: ${{ matrix.ruby_version }}
84
+ ruby-version: ${{ matrix.ruby-version }}
57
85
  bundler-cache: true
58
86
 
59
- - name: Install correct gems / rails version
87
+ - name: Install Gems w/ Rails ${{ matrix.rails }}
60
88
  env:
61
89
  MATRIX_RAILS_VERSION: ${{ matrix.rails }}
62
90
  run: |
@@ -66,3 +94,4 @@ jobs:
66
94
 
67
95
  - name: Run tests
68
96
  run: bundle exec rspec
97
+
data/CHANGELOG.md CHANGED
@@ -1,10 +1,33 @@
1
1
  # Changelog
2
2
 
3
- ## [1.0.1] - 2020-12-30
3
+ ## [2.1.0] - 2022-01-12
4
+ - change CI matrix for more version compatibility
5
+ - update gemspec to move some deps into development only
6
+ - README changes
7
+
8
+ ## [2.0.0] - 2022-01-07
9
+ - Require much more recent ruby, to use syntax that's been around since 2017
10
+
11
+ ## [1.3.0] - 2021-12-31
12
+ - Add `repeatedly_load` matcher
13
+ - Add query type matchers for `load_queries`, `schema_queries`, `transaction_queries`, `destroy_queries`
14
+ - Allow singular version of all query types (e.g. `transaction_queries` vs `transaction_query`)
15
+ - Fix failure message for `execute.exactly` matcher
16
+
17
+ ## [1.2.0] - 2021-12-31
18
+ - Add `query` as a synonym for `queries`
19
+ - Ignore schema and transaction queries in query count
20
+ - Add beginning of recording specific query types
21
+ - Add query count matcher for `exactly`
22
+
23
+ ## [1.1.0] - 2021-12-30
24
+ - Add query count matchers for e.g. `less_than_or_equal_to`, `greater_than`
25
+
26
+ ## [1.0.1] - 2021-12-30
4
27
  - Pin all the dependencies to a proper working subset
5
28
  - Expand testing to many rails / ruby combinations
6
29
 
7
- ## [1.0.0] - 2020-12-30
30
+ ## [1.0.0] - 2021-12-30
8
31
  - Basic gem w/ all the fixins and README and such
9
32
  - Add `less_than` comparison, and `queries` type
10
33
  - Basic tests in place, and not bad tbh
data/README.md CHANGED
@@ -30,7 +30,8 @@ group 'test' do
30
30
  end
31
31
  ```
32
32
 
33
- Then, include the functionality within your spec helper (or in a support file).
33
+ Then, include the functionality within your `rails_helper.rb` (or in a support
34
+ file).
34
35
 
35
36
  ```ruby
36
37
  RSpec.configure do |config|
@@ -91,11 +92,91 @@ That's it! Refactor your report to be more efficient and then leave the test in
91
92
  place to make sure that future developers don't accidentally cause a
92
93
  performance regression.
93
94
 
94
- ## Supported Matchers
95
+ ## Preventing Repeated Load (N+1) Queries
96
+
97
+ Reloading, whether by e.g. `Album.find` or `album.tracks` are both antipatterns
98
+ within your code. They will load from the database for every iteration in a
99
+ loop, unless you load records outside the loop, cache responses, or use an
100
+ eager loading mechanism like `includes`. These sorts of queries are often
101
+ referred to as N+1 queries.
102
+
103
+ This sort of query can be prevented using the `repeatedly_load` expectation.
104
+
105
+ ```ruby
106
+ expect {}.not_to repeatedly_load('SomeActiveRecordClass')
107
+ ```
108
+
109
+ This matcher will track ActiveRecord's built in load methods to prevent those
110
+ N+1 situations. Using eager loading (e.g. `Track.all.includes(:album)`) will
111
+ allow these expectations to pass as expected!
112
+
113
+ ### Testing Batch Queries
114
+
115
+ If your code loads records in batches, it may be more difficult to create
116
+ expectations for repeated loading. After all, each batch will execute its own
117
+ queries, which may look like repeated loading.
118
+
119
+ If your test has a small enough number of records that only one batch is
120
+ loaded, your tests may work just fine. But otherwise, you may want to allow
121
+ your code to specify a batch size in order to guarantee only a single batch
122
+ is loaded:
95
123
 
96
124
  ```ruby
125
+ tracks = Track.all
126
+
127
+ expect {
128
+ TrackSerializer.perform(tracks, batch_size: tracks.count)
129
+ }.not_to repeatedly_load('Track')
130
+ ```
131
+
132
+ ## Counting Queries
133
+
134
+ ### Types of Comparisons
135
+
136
+ Several comparison types are available, along with some aliases to allow for
137
+ easier to read tests.
138
+
139
+ ```ruby
140
+ expect {}.to execute.less_than(20).queries
97
141
  expect {}.to execute.fewer_than(20).queries
98
- expect {}.to execute.less_than(20).queries # alias for fewer_than
142
+
143
+ expect {}.to execute.less_than_or_equal_to(20).queries
144
+ expect {}.to execute.at_most(20).queries
145
+
146
+ expect {}.to execute.greater_than(20).queries
147
+ expect {}.to execute.more_than(20).queries
148
+
149
+ expect {}.to execute.greater_than_or_equal_to(20).queries
150
+ expect {}.to execute.at_least(20).queries
151
+
152
+ expect {}.to execute.exactly(20).queries
153
+
154
+ expect {}.to execute.at_least(2).queries
155
+ expect {}.to execute.at_least(1).query # singular form also accepted
156
+ ```
157
+
158
+ ### Specific Query Types
159
+
160
+ You can of course make assertions for the total number of queries executed, but
161
+ sometimes it's more valuable to assert particular _types_ of queries, such as
162
+ inserts or find statements. Matchers are supported for this as well!
163
+
164
+ **Note:** Transaction (for example, `ROLLBACK`) queries are not counted in any of these
165
+ categories, nor are queries that load the DB schema.
166
+
167
+ **Note:** Destroy and delete queries are both condensed into the matcher for
168
+ `destroy_queries`.
169
+
170
+ ```ruby
171
+ expect {}.to execute.exactly(20).queries
172
+
173
+ expect {}.to execute.exactly(20).insert_queries
174
+ expect {}.to execute.exactly(20).load_queries
175
+ expect {}.to execute.exactly(20).destroy_queries
176
+ expect {}.to execute.exactly(20).exists_queries
177
+
178
+ expect {}.to execute.exactly(20).schema_queries
179
+ expect {}.to execute.exactly(20).transaction_queries
99
180
  ```
100
181
 
101
182
  ## Future Planned Functionality
@@ -103,17 +184,11 @@ expect {}.to execute.less_than(20).queries # alias for fewer_than
103
184
  This gem still has lots of future functionality. See below.
104
185
 
105
186
  ```ruby
106
- expect {}.to execute.more_than(20).activerecord_queries
107
- expect {}.to execute.fewer_than(20).insert_queries
108
- expect {}.to execute.exactly(5).queries
109
- expect {}.to execute.at_least(5).handrolled_queries
110
-
111
- expect {}.to execute.less_than(20).delete_queries
112
- expect {}.to execute.less_than(20).load_queries
113
- expect {}.to execute.less_than(20).schema_queries
114
- expect {}.to execute.less_than(20).exists_queries
115
- expect {}.to execute.less_than(20).queries
116
- expect {}.to execute.less_than(20).queries_of_type("Audited::Audit Load")
187
+ expect {}.to execute.at_least(2).queries_of_type("Audited::Audit Load")
188
+ expect {}.to execute.at_least(2).load_queries("Audited::Audit")
189
+
190
+ expect {}.to execute.at_least(2).activerecord_queries
191
+ expect {}.to execute.at_least(2).hand_rolled_queries
117
192
 
118
193
  expect {}.not_to rollback_transaction.exactly(5).times
119
194
  expect {}.not_to commit_transaction.once
@@ -123,18 +198,10 @@ expect {}.to create.exactly(5).of_type(User)
123
198
  expect {}.to insert.exactly(5).subscription_changes
124
199
  expect {}.to update.exactly(2).of_any_type
125
200
  expect {}.to delete.exactly(2).of_any_type
126
-
127
- expect {}.not_to repeatedly_load(Audited::Audit)
128
-
129
- at_least, more_than, at_most, less_than, lteq?
130
- exactly(1) => once?
131
201
  ```
132
202
 
133
- - ignore transactionals (begin / rollback)
134
- - `name: Foo Load`
135
- - differentiate AR queries from generic ones? arbitrary execution somehow?
136
- - warn about warmup
137
- - make sure we don't smite any built in methods (or from other libs)
203
+ - warn if we smite any built in methods (or methods from other libs)
204
+ - support Rails 6 bulk insert (still one query)
138
205
 
139
206
  ## Development
140
207
 
@@ -1,23 +1,42 @@
1
1
  module RSpec::ActiveRecord::Expectations
2
2
  class Collector
3
3
  def initialize
4
- @counts = {
5
- queries: 0
6
- }
4
+ @inspector = QueryInspector.new
5
+ @by_name = {}
6
+ @counts = QueryInspector.valid_query_types.each_with_object({}) do |query_type, hash|
7
+ hash[query_type] = 0
8
+ end
7
9
 
8
- ActiveSupport::Notifications.subscribe("sql.active_record", method(:record_query))
10
+ @subscription = ActiveSupport::Notifications.subscribe("sql.active_record", method(:record_query))
11
+ end
12
+
13
+ def finalize
14
+ ActiveSupport::Notifications.unsubscribe(@subscription)
9
15
  end
10
16
 
11
17
  def queries_of_type(type)
12
- @counts.fetch(type)
18
+ @counts[type] || (raise ArgumentError, "Sorry, #{type} is not a valid kind of query")
13
19
  end
14
20
 
15
21
  def valid_type?(type)
16
22
  @counts.include? type
17
23
  end
18
24
 
25
+ def calls_by_name(name)
26
+ @by_name.fetch(name, 0)
27
+ end
28
+
19
29
  def record_query(*_unused, data)
20
- @counts[:queries] += 1
30
+ categories = @inspector.categorize(data)
31
+
32
+ categories.each do |category|
33
+ @counts[category] += 1
34
+ rescue NoMethodError
35
+ raise "tried to add to to #{category} but it doesn't exist"
36
+ end
37
+
38
+ @by_name[data[:name]] ||= 0
39
+ @by_name[data[:name]] += 1
21
40
  end
22
41
  end
23
42
  end
@@ -0,0 +1,29 @@
1
+ module RSpec::ActiveRecord::Expectations
2
+ module Matchers
3
+ class LoadMatcher
4
+ def initialize(klass)
5
+ @collector = Collector.new
6
+ @klass = klass.to_s
7
+ end
8
+
9
+ def supports_block_expectations?
10
+ true
11
+ end
12
+
13
+ def matches?(block)
14
+ block.call
15
+
16
+ @count = @collector.calls_by_name("#{@klass} Load")
17
+ @count > 1
18
+ end
19
+
20
+ def failure_message
21
+ "expected block to repeatedly load #{@klass}, but it was loaded #{@count} times"
22
+ end
23
+
24
+ def failure_message_when_negated
25
+ "expected block not to repeatedly load #{@klass}, but it was loaded #{@count} times"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,141 @@
1
+ module RSpec::ActiveRecord::Expectations
2
+ module Matchers
3
+ class QueryCountMatcher
4
+ attr_reader :failure_message, :failure_message_when_negated
5
+
6
+ def initialize
7
+ @collector = Collector.new
8
+
9
+ @match_method = nil
10
+ @comparison = nil
11
+ @query_type = nil
12
+ end
13
+
14
+ def supports_block_expectations?
15
+ true
16
+ end
17
+
18
+ def matches?(block)
19
+ raise NoComparisonError unless @match_method
20
+ raise NoQueryTypeError unless @collector.valid_type?(@query_type)
21
+
22
+ block.call
23
+ result = @match_method.call
24
+ @collector.finalize
25
+
26
+ result
27
+ end
28
+
29
+ # COMPARISON TYPES
30
+
31
+ def less_than(n)
32
+ @comparison = n
33
+ @match_method = method(:compare_less_than)
34
+ self
35
+ end
36
+ alias_method :fewer_than, :less_than
37
+
38
+ def less_than_or_equal_to(n)
39
+ @comparison = n
40
+ @match_method = method(:compare_less_than_or_equal_to)
41
+ self
42
+ end
43
+ alias_method :at_most, :less_than_or_equal_to
44
+
45
+ def greater_than(n)
46
+ @comparison = n
47
+ @match_method = method(:compare_greater_than)
48
+ self
49
+ end
50
+ alias_method :more_than, :greater_than
51
+
52
+ def greater_than_or_equal_to(n)
53
+ @comparison = n
54
+ @match_method = method(:compare_greater_than_or_equal_to)
55
+ self
56
+ end
57
+ alias_method :at_least, :greater_than_or_equal_to
58
+
59
+ def exactly(n)
60
+ @comparison = n
61
+ @match_method = method(:compare_exactly)
62
+ self
63
+ end
64
+
65
+ # TARGET QUERY TYPES
66
+
67
+ RSpec::ActiveRecord::Expectations::QueryInspector.valid_query_types.each do |type|
68
+ define_method type do
69
+ @query_type = type
70
+ self
71
+ end
72
+
73
+ singularized_type = type.to_s.gsub('queries', 'query')
74
+ if singularized_type != type.to_s
75
+ define_method singularized_type do
76
+ @query_type = type
77
+ self
78
+ end
79
+ end
80
+ end
81
+
82
+ # TODO singularize everything
83
+ alias_method :query, :queries
84
+
85
+ private
86
+
87
+ def humanized_query_type
88
+ @query_type.to_s.gsub("_", " ")
89
+ end
90
+
91
+ # MATCHERS
92
+
93
+ def compare_less_than
94
+ count = @collector.queries_of_type(@query_type)
95
+
96
+ @failure_message = "expected block to execute fewer than #{@comparison} #{humanized_query_type}, but it executed #{count}"
97
+ @failure_message_when_negated = "expected block not to execute fewer than #{@comparison} #{humanized_query_type}, but it executed #{count}"
98
+
99
+ count < @comparison
100
+ end
101
+
102
+ def compare_less_than_or_equal_to
103
+ count = @collector.queries_of_type(@query_type)
104
+
105
+ # boy this negated operator is confusing. don't use that plz.
106
+ @failure_message = "expected block to execute at most #{@comparison} #{humanized_query_type}, but it executed #{count}"
107
+ @failure_message_when_negated = "expected block not to execute any less than #{@comparison} #{humanized_query_type}, but it executed #{count}"
108
+
109
+ count <= @comparison
110
+ end
111
+
112
+ def compare_greater_than
113
+ count = @collector.queries_of_type(@query_type)
114
+
115
+ @failure_message = "expected block to execute greater than #{@comparison} #{humanized_query_type}, but it executed #{count}"
116
+ @failure_message_when_negated = "expected block not to execute greater than #{@comparison} #{humanized_query_type}, but it executed #{count}"
117
+
118
+ count > @comparison
119
+ end
120
+
121
+ def compare_greater_than_or_equal_to
122
+ count = @collector.queries_of_type(@query_type)
123
+
124
+ # see above, negating this matcher is so confusing.
125
+ @failure_message = "expected block to execute at least #{@comparison} #{humanized_query_type}, but it executed #{count}"
126
+ @failure_message_when_negated = "expected block not to execute any more than #{@comparison} #{humanized_query_type}, but it executed #{count}"
127
+
128
+ count >= @comparison
129
+ end
130
+
131
+ def compare_exactly
132
+ count = @collector.queries_of_type(@query_type)
133
+
134
+ @failure_message = "expected block to execute exactly #{@comparison} #{humanized_query_type}, but it executed #{count}"
135
+ @failure_message_when_negated = "expected block not to execute exactly #{@comparison} #{humanized_query_type}, but it executed #{count}"
136
+
137
+ count == @comparison
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,28 @@
1
+ module RSpec::ActiveRecord::Expectations
2
+ class QueryInspector
3
+ def self.valid_query_types
4
+ [:queries, :schema_queries, :transaction_queries, :insert_queries,
5
+ :load_queries, :destroy_queries, :exists_queries]
6
+ end
7
+
8
+ def categorize(query)
9
+ if query[:name] == "SCHEMA"
10
+ [:schema_queries]
11
+ elsif query[:name] == "TRANSACTION" || query[:sql] =~ /^begin/i || query[:sql] =~ /^commit/i
12
+ [:transaction_queries]
13
+ elsif query[:name] =~ /Create$/
14
+ [:queries, :insert_queries]
15
+ elsif query[:name] =~ /Load$/
16
+ [:queries, :load_queries]
17
+ elsif query[:name] =~ /Destroy$/
18
+ [:queries, :destroy_queries]
19
+ elsif query[:name] =~ /Delete All$/
20
+ [:queries, :destroy_queries]
21
+ elsif query[:name] =~ /Exists\??$/
22
+ [:queries, :exists_queries]
23
+ else
24
+ [:queries]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -4,10 +4,16 @@ module RSpec
4
4
  def execute
5
5
  Matchers::QueryCountMatcher.new
6
6
  end
7
+
8
+ def repeatedly_load(klass)
9
+ Matchers::LoadMatcher.new(klass)
10
+ end
7
11
  end
8
12
  end
9
13
  end
10
14
 
11
15
  require_relative 'expectations/errors'
16
+ require_relative 'expectations/query_inspector'
12
17
  require_relative 'expectations/collector'
13
- require_relative 'expectations/matchers/query_count'
18
+ require_relative 'expectations/matchers/query_count_matcher'
19
+ require_relative 'expectations/matchers/load_matcher'
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "rspec-activerecord-expectations"
3
- spec.version = '1.0.1'
3
+ spec.version = '2.1.0'
4
4
  spec.authors = ["Joseph Mastey"]
5
5
  spec.email = ["hello@joemastey.com"]
6
6
 
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.description = %q{Adds new matchers to rspec to help you test whether your code is executing an unreasonable number of queries.}
9
9
  spec.homepage = "https://github.com/jmmastey/rspec-activerecord-expectations"
10
10
  spec.license = "MIT"
11
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
11
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
12
12
 
13
13
  spec.metadata["homepage_uri"] = spec.homepage
14
14
  spec.metadata["source_code_uri"] = spec.homepage
@@ -23,7 +23,12 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_dependency "activerecord", ">= 5.0.0", "< 7.1.0"
26
- spec.add_dependency "sqlite3", "~> 1.0"
26
+
27
+ if RUBY_PLATFORM == 'java'
28
+ spec.add_development_dependency "activerecord-jdbcsqlite3-adapter", '>= 60'
29
+ else
30
+ spec.add_development_dependency "sqlite3", "~> 1.0"
31
+ end
27
32
 
28
33
  spec.add_development_dependency "pry", "~> 0.0"
29
34
  spec.add_development_dependency "appraisal", "~> 2"
metadata CHANGED
@@ -1,17 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-activerecord-expectations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.1.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: 2021-12-30 00:00:00.000000000 Z
11
+ date: 2022-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activerecord
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - ">="
@@ -20,8 +19,9 @@ dependencies:
20
19
  - - "<"
21
20
  - !ruby/object:Gem::Version
22
21
  version: 7.1.0
23
- type: :runtime
22
+ name: activerecord
24
23
  prerelease: false
24
+ type: :runtime
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
@@ -31,42 +31,42 @@ dependencies:
31
31
  - !ruby/object:Gem::Version
32
32
  version: 7.1.0
33
33
  - !ruby/object:Gem::Dependency
34
- name: sqlite3
35
34
  requirement: !ruby/object:Gem::Requirement
36
35
  requirements:
37
- - - "~>"
36
+ - - ">="
38
37
  - !ruby/object:Gem::Version
39
- version: '1.0'
40
- type: :runtime
38
+ version: '60'
39
+ name: activerecord-jdbcsqlite3-adapter
41
40
  prerelease: false
41
+ type: :development
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '1.0'
46
+ version: '60'
47
47
  - !ruby/object:Gem::Dependency
48
- name: pry
49
48
  requirement: !ruby/object:Gem::Requirement
50
49
  requirements:
51
50
  - - "~>"
52
51
  - !ruby/object:Gem::Version
53
52
  version: '0.0'
54
- type: :development
53
+ name: pry
55
54
  prerelease: false
55
+ type: :development
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0.0'
61
61
  - !ruby/object:Gem::Dependency
62
- name: appraisal
63
62
  requirement: !ruby/object:Gem::Requirement
64
63
  requirements:
65
64
  - - "~>"
66
65
  - !ruby/object:Gem::Version
67
66
  version: '2'
68
- type: :development
67
+ name: appraisal
69
68
  prerelease: false
69
+ type: :development
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
@@ -102,7 +102,9 @@ files:
102
102
  - lib/rspec/activerecord/expectations.rb
103
103
  - lib/rspec/activerecord/expectations/collector.rb
104
104
  - lib/rspec/activerecord/expectations/errors.rb
105
- - lib/rspec/activerecord/expectations/matchers/query_count.rb
105
+ - lib/rspec/activerecord/expectations/matchers/load_matcher.rb
106
+ - lib/rspec/activerecord/expectations/matchers/query_count_matcher.rb
107
+ - lib/rspec/activerecord/expectations/query_inspector.rb
106
108
  - rspec-activerecord-expectations.gemspec
107
109
  homepage: https://github.com/jmmastey/rspec-activerecord-expectations
108
110
  licenses:
@@ -119,14 +121,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
121
  requirements:
120
122
  - - ">="
121
123
  - !ruby/object:Gem::Version
122
- version: 2.3.0
124
+ version: 2.5.0
123
125
  required_rubygems_version: !ruby/object:Gem::Requirement
124
126
  requirements:
125
127
  - - ">="
126
128
  - !ruby/object:Gem::Version
127
129
  version: '0'
128
130
  requirements: []
129
- rubygems_version: 3.1.6
131
+ rubygems_version: 3.2.29
130
132
  signing_key:
131
133
  specification_version: 4
132
134
  summary: A gem to test how many activerecord queries your code executes.
@@ -1,57 +0,0 @@
1
- module RSpec::ActiveRecord::Expectations
2
- module Matchers
3
- class QueryCountMatcher
4
- attr_reader :failure_message, :failure_message_when_negated
5
-
6
- def initialize
7
- @collector = Collector.new
8
-
9
- @match_method = nil
10
- @comparison = nil
11
- @query_type = nil
12
- end
13
-
14
- def supports_block_expectations?
15
- true
16
- end
17
-
18
- def matches?(block)
19
- raise NoComparisonError unless @match_method
20
- raise NoQueryTypeError unless @collector.valid_type?(@query_type)
21
-
22
- result = block.call
23
-
24
- !!@match_method.call
25
- end
26
-
27
- # COMPARISON TYPES
28
-
29
- def fewer_than(n)
30
- @comparison = n
31
- @match_method = method(:match_fewer_than)
32
- self
33
- end
34
- alias_method :less_than, :fewer_than
35
-
36
- # TARGET QUERY TYPES
37
-
38
- def queries
39
- @query_type = :queries
40
- self
41
- end
42
-
43
- private
44
-
45
- # MATCHERS
46
-
47
- def match_fewer_than
48
- count = @collector.queries_of_type(@query_type)
49
-
50
- @failure_message = "expected block to execute fewer than #{@comparison} queries, but it executed #{count}"
51
- @failure_message_when_negated = "expected block not to execute fewer than #{@comparison} queries, but it executed #{count}"
52
-
53
- count < @comparison
54
- end
55
- end
56
- end
57
- end