rspec-sidekiq 5.0.0 → 5.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 +4 -4
- data/CHANGES.md +6 -0
- data/README.md +42 -3
- data/lib/rspec/sidekiq/batch.rb +4 -1
- data/lib/rspec/sidekiq/configuration.rb +6 -0
- data/lib/rspec/sidekiq/helpers/within_sidekiq_retries_exhausted_block.rb +5 -3
- data/lib/rspec/sidekiq/helpers.rb +2 -0
- data/lib/rspec/sidekiq/matchers/base.rb +45 -19
- data/lib/rspec/sidekiq/matchers/be_delayed.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_expired_in.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_processed_in.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_retryable.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_unique.rb +23 -1
- data/lib/rspec/sidekiq/matchers/enqueue_sidekiq_job.rb +5 -0
- data/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb +2 -0
- data/lib/rspec/sidekiq/matchers/save_backtrace.rb +2 -0
- data/lib/rspec/sidekiq/matchers.rb +2 -0
- data/lib/rspec/sidekiq/sidekiq.rb +2 -0
- data/lib/rspec/sidekiq/version.rb +3 -1
- data/lib/rspec-sidekiq.rb +2 -0
- metadata +21 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56ce84afbf67491fa24da1f527bced61c54afa3d62dbb50e6a09a89e8c0bc16c
|
4
|
+
data.tar.gz: 5b4a368bbb098d580713009fb9381d66326c37eced31c91eaf85b43158a85db5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ec18b3d6ceff7390807d7358259b44f236ca6d81b1b9175c069b6c4912041b914082042a5396c7cf1eb0b602a5448d9aacd9e23b3cee211ad7222c3ec3719af
|
7
|
+
data.tar.gz: 4f0232e7b482f7c565a5cca98be9b7143e51adbe6015329f9d052e393fd857fe97e2449fb53f9e3d209ff6319c54e23e9e2919e7003a44bfc00834692039eed0
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
Unreleased
|
2
2
|
---
|
3
|
+
* Add `until` matcher for Sidekiq Enterprise unique jobs (#232, #147)
|
4
|
+
* Add `with_context` matcher for matching against job contexts (#222)
|
5
|
+
* Support for Sidekiq 8 (#233)
|
6
|
+
* Add `frozen_string_literal: true` (#220)
|
7
|
+
* Fix queue always nil in default_retries_exhausted_message (#229)
|
8
|
+
* Fix pattern matching warnings on Ruby 2.7 (#227)
|
3
9
|
|
4
10
|
5.0.0
|
5
11
|
---
|
data/README.md
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
**Welcome @wspurgin as new maintainer for `rspec-sidekiq`!**
|
2
|
-
|
3
1
|
[](https://badge.fury.io/rb/rspec-sidekiq)
|
4
2
|
[![Github Actions CI][github_actions_badge]][github_actions]
|
5
3
|
|
@@ -81,6 +79,17 @@ expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(2).times
|
|
81
79
|
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:twice)
|
82
80
|
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:thrice)
|
83
81
|
|
82
|
+
# With specific context:
|
83
|
+
# Useful for testing anything `set` on the job, including
|
84
|
+
# overrides to things like `retry`
|
85
|
+
expect {
|
86
|
+
AwesomeJob.set(trace_id: "something").perform_async
|
87
|
+
}.to enqueue_sidekiq_job.with_context(trace_id: anything)
|
88
|
+
|
89
|
+
expect {
|
90
|
+
AwesomeJob.set(retry: 5).perform_async
|
91
|
+
}.to enqueue_sidekiq_job.with_context(retry: 5)
|
92
|
+
|
84
93
|
# Combine and chain them as desired
|
85
94
|
expect { AwesomeJob.perform_at(specific_time, "Awesome!") }.to(
|
86
95
|
enqueue_sidekiq_job(AwesomeJob)
|
@@ -133,6 +142,13 @@ expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:twice)
|
|
133
142
|
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:thrice)
|
134
143
|
```
|
135
144
|
|
145
|
+
Likewise, specify what should be in the context:
|
146
|
+
```ruby
|
147
|
+
AwesomeJob.set(trace_id: "something").perform_async
|
148
|
+
|
149
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.with_context(trace_id: anything)
|
150
|
+
```
|
151
|
+
|
136
152
|
#### Testing scheduled jobs
|
137
153
|
|
138
154
|
*Use chainable matchers `#at`, `#in` and `#immediately`*
|
@@ -204,6 +220,10 @@ it { is_expected.to be_processed_in :download }
|
|
204
220
|
|
205
221
|
### ```be_retryable```
|
206
222
|
*Describes if a job should retry when there is a failure in its execution*
|
223
|
+
|
224
|
+
Note: this only tests against the `retry` option in the job's Sidekiq options.
|
225
|
+
To test an enqueued job's retry, i.e. `AwesomeJob.set(retry: 5)`, use
|
226
|
+
`with_context`
|
207
227
|
```ruby
|
208
228
|
sidekiq_options retry: 5
|
209
229
|
# test with...
|
@@ -235,14 +255,33 @@ it { is_expected.to save_backtrace false }
|
|
235
255
|
```
|
236
256
|
|
237
257
|
### ```be_unique```
|
258
|
+
|
259
|
+
:warning: This is intended to for Sidekiq Enterprise unique job implementation.
|
260
|
+
There is _limited_ support for Sidekiq Unique Jobs, but compatibility is not
|
261
|
+
guaranteed.
|
262
|
+
|
238
263
|
*Describes when a job should be unique within its queue*
|
239
264
|
```ruby
|
240
|
-
sidekiq_options
|
265
|
+
sidekiq_options unique_for: 1.hour
|
241
266
|
# test with...
|
242
267
|
expect(AwesomeJob).to be_unique
|
243
268
|
it { is_expected.to be_unique }
|
269
|
+
|
270
|
+
# specify a specific interval
|
271
|
+
sidekiq_options unique_for: 1.hour
|
272
|
+
it { is_expected.to be_unique.for(1.hour) }
|
273
|
+
```
|
274
|
+
|
275
|
+
#### `until` sub-matcher
|
276
|
+
|
277
|
+
:warning: This sub-matcher only works for Sidekiq Enterprise
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
sidekiq_options unique_for: 1.hour, unique_until: :start
|
281
|
+
it { is_expected.to be_unique.until(:start) }
|
244
282
|
```
|
245
283
|
|
284
|
+
|
246
285
|
### ```be_expired_in```
|
247
286
|
*Describes when a job should expire*
|
248
287
|
```ruby
|
data/lib/rspec/sidekiq/batch.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rubygems"
|
2
4
|
require "set"
|
3
5
|
|
@@ -22,6 +24,10 @@ module RSpec
|
|
22
24
|
Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("7.0.0")
|
23
25
|
end
|
24
26
|
|
27
|
+
def sidekiq_gte_8?
|
28
|
+
Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("8.0.0")
|
29
|
+
end
|
30
|
+
|
25
31
|
def silence_warning(symbol)
|
26
32
|
@silence_warnings << symbol
|
27
33
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sidekiq
|
2
4
|
module Worker
|
3
5
|
module ClassMethods
|
@@ -8,15 +10,15 @@ module Sidekiq
|
|
8
10
|
|
9
11
|
def default_retries_exhausted_message
|
10
12
|
{
|
11
|
-
'queue' => get_sidekiq_options[
|
13
|
+
'queue' => get_sidekiq_options['queue'],
|
12
14
|
'class' => name,
|
13
15
|
'args' => [],
|
14
|
-
'error_message' => 'An error
|
16
|
+
'error_message' => 'An error occurred'
|
15
17
|
}
|
16
18
|
end
|
17
19
|
|
18
20
|
def default_retries_exhausted_exception
|
19
|
-
StandardError.new('An error
|
21
|
+
StandardError.new('An error occurred')
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Sidekiq
|
3
5
|
module Matchers
|
@@ -26,7 +28,7 @@ module RSpec
|
|
26
28
|
# send to custom evaluator
|
27
29
|
at_evaluator(value)
|
28
30
|
else
|
29
|
-
job.context.has_key?(key) && job.context[key]
|
31
|
+
job.context.has_key?(key) && RSpec::Support::FuzzyMatcher.values_match?(value, job.context[key])
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
@@ -58,7 +60,11 @@ module RSpec
|
|
58
60
|
private
|
59
61
|
|
60
62
|
def active_job?
|
61
|
-
|
63
|
+
if RSpec::Sidekiq.configuration.sidekiq_gte_8?
|
64
|
+
job["class"] == "Sidekiq::ActiveJob::Wrapper"
|
65
|
+
else
|
66
|
+
job["class"] == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
67
|
+
end
|
62
68
|
end
|
63
69
|
|
64
70
|
def deserialized_active_job_args
|
@@ -121,13 +127,13 @@ module RSpec
|
|
121
127
|
def includes?(arguments, options, count)
|
122
128
|
matching = jobs.filter { |job| matches?(job, arguments, options) }
|
123
129
|
|
124
|
-
case count
|
125
|
-
|
126
|
-
matching.size ==
|
127
|
-
|
128
|
-
matching.size >=
|
129
|
-
|
130
|
-
matching.size <=
|
130
|
+
case count[0]
|
131
|
+
when :exactly
|
132
|
+
matching.size == count[1]
|
133
|
+
when :at_least
|
134
|
+
matching.size >= count[1]
|
135
|
+
when :at_most
|
136
|
+
matching.size <= count[1]
|
131
137
|
else
|
132
138
|
matching.size > 0
|
133
139
|
end
|
@@ -243,6 +249,26 @@ module RSpec
|
|
243
249
|
end
|
244
250
|
alias :time :times
|
245
251
|
|
252
|
+
def with_context(**kwargs)
|
253
|
+
raise ArgumentError, "Must specify keyword arguments to with_context" if kwargs.empty?
|
254
|
+
|
255
|
+
# gather keys and compare against currently set expected_options
|
256
|
+
# Someone could have accidentally used with_context and other
|
257
|
+
# chainables with different expectations. Better to explicitly
|
258
|
+
# inform loudly of clashes than let them overwrite silently
|
259
|
+
normalized = normalize_arguments(kwargs)
|
260
|
+
already_set = normalized.keys & @expected_options.keys
|
261
|
+
if already_set.any?
|
262
|
+
prettied = already_set.map { |key| "'#{key}'" }
|
263
|
+
raise ArgumentError, "There are already expectations against #{prettied.join(",")}. Did you already call other context chainables like `on` or `at`?"
|
264
|
+
end
|
265
|
+
|
266
|
+
# We're good, no accidental overwrites of expectations
|
267
|
+
@expected_options.merge!(normalized)
|
268
|
+
|
269
|
+
self
|
270
|
+
end
|
271
|
+
|
246
272
|
def set_expected_count(relativity, n)
|
247
273
|
n =
|
248
274
|
case n
|
@@ -275,13 +301,13 @@ module RSpec
|
|
275
301
|
message << "but enqueued only jobs"
|
276
302
|
if expected_arguments
|
277
303
|
job_messages = actual_jobs.map do |job|
|
278
|
-
base = " -JID:#{job.jid} with arguments:"
|
279
|
-
base << "
|
304
|
+
base = [" -JID:#{job.jid} with arguments:"]
|
305
|
+
base << " -#{formatted(job.args)}"
|
280
306
|
if expected_options.any?
|
281
|
-
base << "
|
307
|
+
base << " with context: #{formatted(job.context)}"
|
282
308
|
end
|
283
309
|
|
284
|
-
base
|
310
|
+
base.join("\n")
|
285
311
|
end
|
286
312
|
|
287
313
|
message << job_messages.join("\n")
|
@@ -302,13 +328,13 @@ module RSpec
|
|
302
328
|
end
|
303
329
|
|
304
330
|
def count_message
|
305
|
-
case expected_count
|
306
|
-
|
331
|
+
case expected_count[0]
|
332
|
+
when :positive
|
307
333
|
"a"
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
"#{
|
334
|
+
when :exactly
|
335
|
+
expected_count[1]
|
336
|
+
else
|
337
|
+
"#{expected_count[0].to_s.gsub('_', ' ')} #{expected_count[1]}"
|
312
338
|
end
|
313
339
|
end
|
314
340
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Sidekiq
|
3
5
|
module Matchers
|
@@ -25,6 +27,9 @@ module RSpec
|
|
25
27
|
if !interval_matches? && @expected_interval
|
26
28
|
"expected #{@klass} to be unique for #{@expected_interval} seconds, "\
|
27
29
|
"but its interval was #{actual_interval} seconds"
|
30
|
+
elsif !expiration_matches?
|
31
|
+
"expected #{@klass} to be unique until #{@expected_expiration}, "\
|
32
|
+
"but its unique_until was #{actual_expiration || 'not specified'}"
|
28
33
|
else
|
29
34
|
"expected #{@klass} to be unique in the queue"
|
30
35
|
end
|
@@ -33,7 +38,7 @@ module RSpec
|
|
33
38
|
def matches?(job)
|
34
39
|
@klass = job.is_a?(Class) ? job : job.class
|
35
40
|
@actual = @klass.get_sidekiq_options[unique_key]
|
36
|
-
!!(value_matches? && interval_matches?)
|
41
|
+
!!(value_matches? && interval_matches? && expiration_matches?)
|
37
42
|
end
|
38
43
|
|
39
44
|
def for(interval)
|
@@ -41,6 +46,11 @@ module RSpec
|
|
41
46
|
self
|
42
47
|
end
|
43
48
|
|
49
|
+
def until(expiration)
|
50
|
+
@expected_expiration = expiration
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
44
54
|
def interval_specified?
|
45
55
|
@expected_interval
|
46
56
|
end
|
@@ -49,6 +59,10 @@ module RSpec
|
|
49
59
|
!interval_specified? || actual_interval == @expected_interval
|
50
60
|
end
|
51
61
|
|
62
|
+
def expiration_matches?
|
63
|
+
@expected_expiration.nil? || actual_expiration == @expected_expiration
|
64
|
+
end
|
65
|
+
|
52
66
|
def failure_message_when_negated
|
53
67
|
"expected #{@klass} to not be unique in the queue"
|
54
68
|
end
|
@@ -59,6 +73,10 @@ module RSpec
|
|
59
73
|
@klass.get_sidekiq_options['unique_job_expiration']
|
60
74
|
end
|
61
75
|
|
76
|
+
def actual_expiration
|
77
|
+
fail 'until is not supported for SidekiqUniqueJobs'
|
78
|
+
end
|
79
|
+
|
62
80
|
def value_matches?
|
63
81
|
[true, :all].include?(@actual)
|
64
82
|
end
|
@@ -73,6 +91,10 @@ module RSpec
|
|
73
91
|
@actual
|
74
92
|
end
|
75
93
|
|
94
|
+
def actual_expiration
|
95
|
+
@klass.get_sidekiq_options['unique_until']
|
96
|
+
end
|
97
|
+
|
76
98
|
def value_matches?
|
77
99
|
@actual && @actual > 0
|
78
100
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Sidekiq
|
3
5
|
module Matchers
|
@@ -72,6 +74,9 @@ module RSpec
|
|
72
74
|
# expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.immediately
|
73
75
|
# expect { AwesomeJob.perform_at(1.hour.ago) }.to enqueue_sidekiq_job.immediately
|
74
76
|
#
|
77
|
+
# # With specific context
|
78
|
+
# expect { AwesomeJob.set(trace_id: "something").perform_async }.to enqueue_sidekiq_job.with_context(trace_id: anything)
|
79
|
+
#
|
75
80
|
# ## Composable
|
76
81
|
#
|
77
82
|
# expect do
|
data/lib/rspec-sidekiq.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aidan Coyle
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2025-03-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec-core
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
version: '5'
|
64
64
|
- - "<"
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
66
|
+
version: '9'
|
67
67
|
type: :runtime
|
68
68
|
prerelease: false
|
69
69
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -73,7 +73,7 @@ dependencies:
|
|
73
73
|
version: '5'
|
74
74
|
- - "<"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '9'
|
77
77
|
- !ruby/object:Gem::Dependency
|
78
78
|
name: pry
|
79
79
|
requirement: !ruby/object:Gem::Requirement
|
@@ -228,6 +228,20 @@ dependencies:
|
|
228
228
|
- - ">="
|
229
229
|
- !ruby/object:Gem::Version
|
230
230
|
version: '0'
|
231
|
+
- !ruby/object:Gem::Dependency
|
232
|
+
name: railties
|
233
|
+
requirement: !ruby/object:Gem::Requirement
|
234
|
+
requirements:
|
235
|
+
- - ">="
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
238
|
+
type: :development
|
239
|
+
prerelease: false
|
240
|
+
version_requirements: !ruby/object:Gem::Requirement
|
241
|
+
requirements:
|
242
|
+
- - ">="
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
version: '0'
|
231
245
|
description: Simple testing of Sidekiq jobs via a collection of matchers and helpers
|
232
246
|
email:
|
233
247
|
executables: []
|
@@ -257,7 +271,8 @@ files:
|
|
257
271
|
homepage: http://github.com/wspurgin/rspec-sidekiq
|
258
272
|
licenses:
|
259
273
|
- MIT
|
260
|
-
metadata:
|
274
|
+
metadata:
|
275
|
+
changelog_uri: https://github.com/wspurgin/rspec-sidekiq/blob/main/CHANGES.md
|
261
276
|
post_install_message:
|
262
277
|
rdoc_options: []
|
263
278
|
require_paths:
|
@@ -273,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
273
288
|
- !ruby/object:Gem::Version
|
274
289
|
version: '0'
|
275
290
|
requirements: []
|
276
|
-
rubygems_version: 3.
|
291
|
+
rubygems_version: 3.5.22
|
277
292
|
signing_key:
|
278
293
|
specification_version: 4
|
279
294
|
summary: RSpec for Sidekiq
|